diff options
-rw-r--r-- | linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c | 139 | ||||
-rw-r--r-- | linux-2.6-xen-sparse/arch/xen/x86_64/mm/ioremap.c | 31 | ||||
-rw-r--r-- | linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c | 12 | ||||
-rw-r--r-- | linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h | 10 | ||||
-rw-r--r-- | linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h | 6 | ||||
-rw-r--r-- | linux-2.6-xen-sparse/include/linux/mm.h | 6 | ||||
-rw-r--r-- | linux-2.6-xen-sparse/mm/memory.c | 102 |
7 files changed, 205 insertions, 101 deletions
diff --git a/linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c b/linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c index 86a3672e33..76f4df0115 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c +++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c @@ -298,90 +298,20 @@ void __init bt_iounmap(void *addr, unsigned long size) #define direct_mk_pte_phys(physpage, pgprot) \ __direct_mk_pte((physpage) >> PAGE_SHIFT, pgprot) -static inline void direct_remap_area_pte(pte_t *pte, - unsigned long address, - unsigned long size, - mmu_update_t **v) -{ - unsigned long end; - - address &= ~PMD_MASK; - end = address + size; - if (end > PMD_SIZE) - end = PMD_SIZE; - if (address >= end) - BUG(); - - do { - (*v)->ptr = virt_to_machine(pte); - (*v)++; - address += PAGE_SIZE; - pte++; - } while (address && (address < end)); -} -static inline int direct_remap_area_pmd(struct mm_struct *mm, - pmd_t *pmd, - unsigned long address, - unsigned long size, - mmu_update_t **v) +static int direct_remap_area_pte_fn(pte_t *pte, + struct page *pte_page, + unsigned long address, + void *data) { - unsigned long end; - - address &= ~PGDIR_MASK; - end = address + size; - if (end > PGDIR_SIZE) - end = PGDIR_SIZE; - if (address >= end) - BUG(); - do { - pte_t *pte = (mm == &init_mm) ? - pte_alloc_kernel(mm, pmd, address) : - pte_alloc_map(mm, pmd, address); - if (!pte) - return -ENOMEM; - direct_remap_area_pte(pte, address, end - address, v); - pte_unmap(pte); - address = (address + PMD_SIZE) & PMD_MASK; - pmd++; - } while (address && (address < end)); - return 0; -} - -int __direct_remap_area_pages(struct mm_struct *mm, - unsigned long address, - unsigned long size, - mmu_update_t *v) -{ - pgd_t * dir; - unsigned long end = address + size; - int error; - - dir = pgd_offset(mm, address); - if (address >= end) - BUG(); - spin_lock(&mm->page_table_lock); - do { - pud_t *pud; - pmd_t *pmd; - - error = -ENOMEM; - pud = pud_alloc(mm, dir, address); - if (!pud) - break; - pmd = pmd_alloc(mm, pud, address); - if (!pmd) - break; - error = 0; - direct_remap_area_pmd(mm, pmd, address, end - address, &v); - address = (address + PGDIR_SIZE) & PGDIR_MASK; - dir++; - - } while (address && (address < end)); - spin_unlock(&mm->page_table_lock); - return error; -} + mmu_update_t **v = (mmu_update_t **)data; + (*v)->ptr = (pfn_to_mfn(page_to_pfn(pte_page)) << PAGE_SHIFT) + | ((unsigned long)pte & ~PAGE_MASK); + (*v)++; + + return 0; +} int direct_remap_area_pages(struct mm_struct *mm, unsigned long address, @@ -393,7 +323,7 @@ int direct_remap_area_pages(struct mm_struct *mm, int i; unsigned long start_address; #define MAX_DIRECTMAP_MMU_QUEUE 130 - mmu_update_t u[MAX_DIRECTMAP_MMU_QUEUE], *v = u; + mmu_update_t u[MAX_DIRECTMAP_MMU_QUEUE], *v = u, *w = u; start_address = address; @@ -402,10 +332,9 @@ int direct_remap_area_pages(struct mm_struct *mm, for (i = 0; i < size; i += PAGE_SIZE) { if ((v - u) == MAX_DIRECTMAP_MMU_QUEUE) { /* Fill in the PTE pointers. */ - __direct_remap_area_pages(mm, - start_address, - address-start_address, - u); + generic_page_range(mm, start_address, + address-start_address, + direct_remap_area_pte_fn, &w); if (HYPERVISOR_mmu_update(u, v - u, NULL, domid) < 0) return -EFAULT; @@ -426,10 +355,9 @@ int direct_remap_area_pages(struct mm_struct *mm, if (v != u) { /* get the ptep's filled in */ - __direct_remap_area_pages(mm, - start_address, - address-start_address, - u); + generic_page_range(mm, start_address, + address-start_address, + direct_remap_area_pte_fn, &w); if (unlikely(HYPERVISOR_mmu_update(u, v - u, NULL, domid) < 0)) return -EFAULT; } @@ -440,3 +368,34 @@ int direct_remap_area_pages(struct mm_struct *mm, } EXPORT_SYMBOL(direct_remap_area_pages); + +int create_lookup_pte_addr(struct mm_struct *mm, + unsigned long address, + unsigned long *ptep) +{ + int f(pte_t *pte, struct page *pte_page, unsigned long addr, void *data) + { + unsigned long *ptep = (unsigned long *)data; + if (ptep) *ptep = (pfn_to_mfn(page_to_pfn(pte_page)) << PAGE_SHIFT) + | ((unsigned long)pte & ~PAGE_MASK); + return 0; + } + + return generic_page_range(mm, address, PAGE_SIZE, f, ptep); +} + +EXPORT_SYMBOL(create_lookup_pte_addr); + +int touch_pte_range(struct mm_struct *mm, + unsigned long address, + unsigned long size) +{ + int f(pte_t *pte, struct page *pte_page, unsigned long addr, void *data) + { + return 0; + } + + return generic_page_range(mm, address, size, f, NULL); +} + +EXPORT_SYMBOL(touch_pte_range); diff --git a/linux-2.6-xen-sparse/arch/xen/x86_64/mm/ioremap.c b/linux-2.6-xen-sparse/arch/xen/x86_64/mm/ioremap.c index 3714880f72..c3d6ee3959 100644 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/mm/ioremap.c +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/mm/ioremap.c @@ -464,3 +464,34 @@ int direct_remap_area_pages(struct mm_struct *mm, } EXPORT_SYMBOL(direct_remap_area_pages); + +int create_lookup_pte_addr(struct mm_struct *mm, + unsigned long address, + unsigned long *ptep) +{ + int f(pte_t *pte, struct page *pte_page, unsigned long addr, void *data) + { + unsigned long *ptep = (unsigned long *)data; + if (ptep) *ptep = (pfn_to_mfn(page_to_pfn(pte_page)) << PAGE_SHIFT) + | ((unsigned long)pte & ~PAGE_MASK); + return 0; + } + + return generic_page_range(mm, address, PAGE_SIZE, f, ptep); +} + +EXPORT_SYMBOL(create_lookup_pte_addr); + +int touch_pte_range(struct mm_struct *mm, + unsigned long address, + unsigned long size) +{ + int f(pte_t *pte, struct page *pte_page, unsigned long addr, void *data) + { + return 0; + } + + return generic_page_range(mm, address, size, f, NULL); +} + +EXPORT_SYMBOL(touch_pte_range); diff --git a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c index e7f6ff5fcf..f72b168d14 100644 --- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c +++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c @@ -139,7 +139,7 @@ static int privcmd_ioctl(struct inode *inode, struct file *file, privcmd_mmapbatch_t m; struct vm_area_struct *vma = NULL; unsigned long *p, addr; - unsigned long mfn; + unsigned long mfn, ptep; int i; if ( copy_from_user(&m, (void *)data, sizeof(m)) ) @@ -163,12 +163,12 @@ static int privcmd_ioctl(struct inode *inode, struct file *file, if ( get_user(mfn, p) ) return -EFAULT; - u.val = (mfn << PAGE_SHIFT) | pgprot_val(vma->vm_page_prot); + ret = create_lookup_pte_addr(vma->vm_mm, addr, &ptep); + if (ret) + goto batch_err; - __direct_remap_area_pages(vma->vm_mm, - addr, - PAGE_SIZE, - &u); + u.val = (mfn << PAGE_SHIFT) | pgprot_val(vma->vm_page_prot); + u.ptr = ptep; if ( unlikely(HYPERVISOR_mmu_update(&u, 1, NULL, m.dom) < 0) ) put_user(0xF0000000 | mfn, p); diff --git a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h index d8066ea6f7..d326f7903a 100644 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h @@ -466,10 +466,12 @@ int direct_remap_area_pages(struct mm_struct *mm, unsigned long size, pgprot_t prot, domid_t domid); -int __direct_remap_area_pages(struct mm_struct *mm, - unsigned long address, - unsigned long size, - mmu_update_t *v); +int create_lookup_pte_addr(struct mm_struct *mm, + unsigned long address, + unsigned long *ptep); +int touch_pte_range(struct mm_struct *mm, + unsigned long address, + unsigned long size); #define io_remap_page_range(vma,from,phys,size,prot) \ direct_remap_area_pages(vma->vm_mm,from,phys,size,prot,DOMID_IO) diff --git a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h index 1884867a8d..20c856360e 100644 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h @@ -538,6 +538,12 @@ int __direct_remap_area_pages(struct mm_struct *mm, unsigned long address, unsigned long size, mmu_update_t *v); +int create_lookup_pte_addr(struct mm_struct *mm, + unsigned long address, + unsigned long *ptep); +int touch_pte_range(struct mm_struct *mm, + unsigned long address, + unsigned long size); #define io_remap_page_range(vma, vaddr, paddr, size, prot) \ direct_remap_area_pages((vma)->vm_mm,vaddr,paddr,size,prot,DOMID_IO) diff --git a/linux-2.6-xen-sparse/include/linux/mm.h b/linux-2.6-xen-sparse/include/linux/mm.h index 12763056cb..79b61e8b50 100644 --- a/linux-2.6-xen-sparse/include/linux/mm.h +++ b/linux-2.6-xen-sparse/include/linux/mm.h @@ -817,6 +817,12 @@ extern int check_user_page_readable(struct mm_struct *mm, unsigned long address) int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long, unsigned long, pgprot_t); +typedef int (*pte_fn_t)(pte_t *pte, struct page *pte_page, unsigned long addr, + void *data); +extern int generic_page_range(struct mm_struct *mm, unsigned long address, + unsigned long size, pte_fn_t fn, void *data); + + #ifdef CONFIG_PROC_FS void __vm_stat_account(struct mm_struct *, unsigned long, struct file *, long); #else diff --git a/linux-2.6-xen-sparse/mm/memory.c b/linux-2.6-xen-sparse/mm/memory.c index d62656eb8e..2726818854 100644 --- a/linux-2.6-xen-sparse/mm/memory.c +++ b/linux-2.6-xen-sparse/mm/memory.c @@ -954,8 +954,10 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, i++; start += PAGE_SIZE; len--; +printk(KERN_ALERT "HIT 0x%lx\n", start); continue; - } + } +else printk(KERN_ALERT "MISS 0x%lx\n", start); } if (!vma || (vma->vm_flags & VM_IO) @@ -1213,6 +1215,104 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, } EXPORT_SYMBOL(remap_pfn_range); +static inline int generic_pte_range(struct mm_struct *mm, + pmd_t *pmd, + unsigned long addr, + unsigned long end, + pte_fn_t fn, void *data) +{ + pte_t *pte; + int err; + struct page *pte_page; + + pte = (mm == &init_mm) ? + pte_alloc_kernel(mm, pmd, addr) : + pte_alloc_map(mm, pmd, addr); + if (!pte) + return -ENOMEM; + + pte_page = pmd_page(*pmd); + + do { + err = fn(pte, pte_page, addr, data); + if (err) + break; + } while (pte++, addr += PAGE_SIZE, addr != end); + + if (mm != &init_mm) + pte_unmap(pte-1); + return err; + +} + +static inline int generic_pmd_range(struct mm_struct *mm, + pud_t *pud, + unsigned long addr, + unsigned long end, + pte_fn_t fn, void *data) +{ + pmd_t *pmd; + unsigned long next; + int err; + + pmd = pmd_alloc(mm, pud, addr); + if (!pmd) + return -ENOMEM; + do { + next = pmd_addr_end(addr, end); + err = generic_pte_range(mm, pmd, addr, next, fn, data); + if (err) + break; + } while (pmd++, addr = next, addr != end); + return err; +} + +static inline int generic_pud_range(struct mm_struct *mm, pgd_t *pgd, + unsigned long addr, + unsigned long end, + pte_fn_t fn, void *data) +{ + pud_t *pud; + unsigned long next; + int err; + + pud = pud_alloc(mm, pgd, addr); + if (!pud) + return -ENOMEM; + do { + next = pud_addr_end(addr, end); + err = generic_pmd_range(mm, pud, addr, next, fn, data); + if (err) + break; + } while (pud++, addr = next, addr != end); + return err; +} + +/* + * Scan a region of virtual memory, filling in page tables as necessary + * and calling a provided function on each leaf page table. + */ +int generic_page_range(struct mm_struct *mm, unsigned long addr, + unsigned long size, pte_fn_t fn, void *data) +{ + pgd_t *pgd; + unsigned long next; + unsigned long end = addr + size; + int err; + + BUG_ON(addr >= end); + pgd = pgd_offset(mm, addr); + spin_lock(&mm->page_table_lock); + do { + next = pgd_addr_end(addr, end); + err = generic_pud_range(mm, pgd, addr, next, fn, data); + if (err) + break; + } while (pgd++, addr = next, addr != end); + spin_unlock(&mm->page_table_lock); + return err; +} + /* * Do pte_mkwrite, but only if the vma says VM_WRITE. We do this when * servicing faults for write access. In the normal case, do always want |