# HG changeset patch # User yamahata@xxxxxxxxxxxxx # Date 1160650695 -32400 # Node ID e265f21c5d694c6cf85472bb62cc2cab4008d911 # Parent f7d65fb7299b95b8b6d3a44134a9f2af211393c6 fix broken IA64 forieng domain page mapping. Cset 11726 broke IA64 foreign domain page mapping accidentally because xenLinux/IA64 already uses vma->vm_private_data for its own purpose. Introduced arch specific functions to check one-shot operation of privcmd mmap. PATCHNAME: fix_privcmd Signed-off-by: Isaku Yamahata diff -r f7d65fb7299b -r e265f21c5d69 linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c --- a/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c Tue Oct 10 22:04:01 2006 +0100 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c Thu Oct 12 19:58:15 2006 +0900 @@ -546,6 +546,7 @@ struct xen_ia64_privcmd_range { }; struct xen_ia64_privcmd_vma { + int is_privcmd_mmapped; struct xen_ia64_privcmd_range* range; unsigned long num_entries; @@ -684,12 +685,15 @@ static void static void xen_ia64_privcmd_vma_open(struct vm_area_struct* vma) { + struct xen_ia64_privcmd_vma* old_privcmd_vma = (struct xen_ia64_privcmd_vma*)vma->vm_private_data; struct xen_ia64_privcmd_vma* privcmd_vma = (struct xen_ia64_privcmd_vma*)vma->vm_private_data; struct xen_ia64_privcmd_range* privcmd_range = privcmd_vma->range; atomic_inc(&privcmd_range->ref_count); // vm_op->open() can't fail. privcmd_vma = kmalloc(sizeof(*privcmd_vma), GFP_KERNEL | __GFP_NOFAIL); + // copy original value if necessary + privcmd_vma->is_privcmd_mmapped = old_privcmd_vma->is_privcmd_mmapped; __xen_ia64_privcmd_vma_open(vma, privcmd_vma, privcmd_range); } @@ -722,6 +726,23 @@ xen_ia64_privcmd_vma_close(struct vm_are kfree(privcmd_range->res); vfree(privcmd_range); } +} + +int +privcmd_is_vma_mmapped(struct vm_area_struct *vma) +{ + struct xen_ia64_privcmd_vma* privcmd_vma = + (struct xen_ia64_privcmd_vma*)vma->vm_private_data; + return privcmd_vma->is_privcmd_mmapped; +} + +void +privcmd_mark_vma_mmapped(struct vm_area_struct *vma) +{ + struct xen_ia64_privcmd_vma* privcmd_vma = + (struct xen_ia64_privcmd_vma*)vma->vm_private_data; + BUG_ON(privcmd_vma->is_privcmd_mmapped); + privcmd_vma->is_privcmd_mmapped = 1; } int @@ -749,6 +770,8 @@ privcmd_mmap(struct file * file, struct if (privcmd_vma == NULL) { goto out_enomem1; } + privcmd_vma->is_privcmd_mmapped = 0; + res = kzalloc(sizeof(*res), GFP_KERNEL); if (res == NULL) { goto out_enomem1; diff -r f7d65fb7299b -r e265f21c5d69 linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c --- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Tue Oct 10 22:04:01 2006 +0100 +++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Thu Oct 12 19:58:15 2006 +0900 @@ -34,6 +34,10 @@ static struct proc_dir_entry *privcmd_intf; static struct proc_dir_entry *capabilities_intf; +#ifndef HAVE_ARCH_PRIVCMD_MMAP +static int privcmd_is_vma_mmapped(struct vm_area_struct *vma); +static void privcmd_mark_vma_mmapped(struct vm_area_struct *vma); +#endif static int privcmd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data) @@ -122,11 +126,12 @@ static int privcmd_ioctl(struct inode *i vma = find_vma(mm, msg.va); rc = -EINVAL; - if (!vma || (msg.va != vma->vm_start) || vma->vm_private_data) + if (!vma || (msg.va != vma->vm_start) || + privcmd_is_vma_mmapped(vma)) goto mmap_out; /* Mapping is a one-shot operation per vma. */ - vma->vm_private_data = (void *)1; + privcmd_mark_vma_mmapped(vma); va = vma->vm_start; @@ -190,13 +195,13 @@ static int privcmd_ioctl(struct inode *i if (!vma || (m.addr != vma->vm_start) || ((m.addr + (m.num<vm_end) || - vma->vm_private_data) { + privcmd_is_vma_mmapped(vma)) { up_read(&mm->mmap_sem); return -EINVAL; } /* Mapping is a one-shot operation per vma. */ - vma->vm_private_data = (void *)1; + privcmd_mark_vma_mmapped(vma); p = m.arr; addr = m.addr; @@ -227,6 +232,16 @@ static int privcmd_ioctl(struct inode *i } #ifndef HAVE_ARCH_PRIVCMD_MMAP +static int privcmd_is_vma_mmapped(struct vm_area_struct *vma) +{ + return vma->vm_private_data; +} + +static void privcmd_mark_vma_mmapped(struct vm_area_struct *vma) +{ + vma->vm_private_data = (void *)1; +} + static struct page *privcmd_nopage(struct vm_area_struct *vma, unsigned long address, int *type) diff -r f7d65fb7299b -r e265f21c5d69 linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h --- a/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h Tue Oct 10 22:04:01 2006 +0100 +++ b/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h Thu Oct 12 19:58:15 2006 +0900 @@ -138,6 +138,8 @@ int direct_remap_pfn_range(struct vm_are pgprot_t prot, domid_t domid); struct file; +int privcmd_is_vma_mmapped(struct vm_area_struct *vma); +void privcmd_mark_vma_mmapped(struct vm_area_struct *vma); int privcmd_mmap(struct file * file, struct vm_area_struct * vma); #define HAVE_ARCH_PRIVCMD_MMAP