Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S935449AbZDJCm1 (ORCPT ); Thu, 9 Apr 2009 22:42:27 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S935732AbZDJCh5 (ORCPT ); Thu, 9 Apr 2009 22:37:57 -0400 Received: from fg-out-1718.google.com ([72.14.220.155]:52299 "EHLO fg-out-1718.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S935681AbZDJChs (ORCPT ); Thu, 9 Apr 2009 22:37:48 -0400 DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=date:from:to:cc:subject:message-id:mime-version:content-type :content-disposition:user-agent; b=GfE9S+BAXtdhQjXJRAS7rXKIaaJYexV13Yabh4XPCGXITVP/hdaRp6+F+4j+KpCO6q NW85VsDWcw3BVcJVKzbnfHJopL+O43dSeA83jWMrl1hxkyrIJOoBavGRGVFrB7i48Gl3 s4txWVAIfUKiRr7hDbh2+fif2auFm+OoBStfQ= Date: Fri, 10 Apr 2009 06:37:52 +0400 From: Alexey Dobriyan To: akpm@linux-foundation.org, containers@lists.linux-foundation.org Cc: xemul@parallels.com, serue@us.ibm.com, dave@linux.vnet.ibm.com, mingo@elte.hu, orenl@cs.columbia.edu, hch@infradead.org, torvalds@linux-foundation.org, linux-kernel@vger.kernel.org Subject: [PATCH 18/30] cr: restore vDSO on i386/x86_64 Message-ID: <20090410023752.GS27788@x200.localdomain> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.18 (2008-05-17) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 5431 Lines: 197 FIXME: check VMA has same parameters. FIXME: abort if target kernel has vDSO disabled (?) FIXME: restore pages, vDSO is writable after all. Signed-off-by: Alexey Dobriyan --- arch/x86/vdso/vdso32-setup.c | 6 ++ include/linux/cr.h | 11 +++++ include/linux/mm.h | 5 +- kernel/cr/cr-mm.c | 87 +++++++++++++++++++++++++++++++++++++++++++ mm/mmap.c | 3 + 5 files changed, 110 insertions(+), 2 deletions(-) --- a/arch/x86/vdso/vdso32-setup.c +++ b/arch/x86/vdso/vdso32-setup.c @@ -328,6 +328,10 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, unsigned long start, map_compat_vdso(compat); + if (start) { + addr = start; + goto map; + } if (compat) addr = VDSO_HIGH_BASE; else { @@ -337,7 +341,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, unsigned long start, goto up_fail; } } - +map: if (compat_uses_vma || !compat) { /* * MAYWRITE to allow gdb to COW and set breakpoints --- a/include/linux/cr.h +++ b/include/linux/cr.h @@ -34,6 +34,7 @@ struct cr_object_header { #define CR_OBJ_FILE 3 #define CR_OBJ_VMA 4 #define CR_OBJ_VMA_CONTENT 5 +#define CR_OBJ_VMA_VDSO 6 __u32 cr_type; /* object type */ __u32 cr_len; /* object length in bytes including header */ } __packed; @@ -177,6 +178,16 @@ struct cr_image_vma { cr_pos_t cr_pos_vm_file; } __packed; +struct cr_image_vma_vdso { + struct cr_object_header cr_hdr; + + __u64 cr_vm_start; + __u64 cr_vm_end; + __u64 cr_vm_page_prot; + __u64 cr_vm_flags; + __u64 cr_vm_pgoff; +} __packed; + struct cr_image_vma_content { struct cr_object_header cr_hdr; --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1129,7 +1129,10 @@ extern int may_expand_vm(struct mm_struct *mm, unsigned long npages); extern int install_special_mapping(struct mm_struct *mm, unsigned long addr, unsigned long len, unsigned long flags, struct page **pages); - +#ifdef CONFIG_CR +struct cr_context; +int special_mapping_checkpoint(struct vm_area_struct *vma, struct cr_context *ctx); +#endif extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, --- a/kernel/cr/cr-mm.c +++ b/kernel/cr/cr-mm.c @@ -332,6 +332,88 @@ static int cr_restore_vma(struct cr_context *ctx, loff_t pos) return cr_restore_vma_content(ctx, pos + sizeof(*i)); } +#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES +int special_mapping_checkpoint(struct vm_area_struct *vma, struct cr_context *ctx) +{ + struct cr_image_vma *i; + struct page **page; + unsigned long addr; + int rv; + + i = cr_prepare_image(CR_OBJ_VMA_VDSO, sizeof(*i)); + if (!i) + return -ENOMEM; + + i->cr_vm_start = vma->vm_start; + i->cr_vm_end = vma->vm_end; + i->cr_vm_page_prot = vma->vm_page_prot.pgprot; + i->cr_vm_flags = vma->vm_flags; + i->cr_vm_pgoff = vma->vm_pgoff; + + rv = cr_write(ctx, i, sizeof(*i)); + kfree(i); + if (rv < 0) + return rv; + + page = vma->vm_private_data; + for (addr = vma->vm_start; addr < vma->vm_end; addr += PAGE_SIZE) { + struct cr_image_vma_content i; + void *data; + + i.cr_hdr.cr_type = CR_OBJ_VMA_CONTENT; + i.cr_hdr.cr_len = sizeof(i) + 1 * PAGE_SIZE; + + i.cr_start_addr = addr; + i.cr_nr_pages = 1; + i.cr_page_size = PAGE_SIZE; + rv = cr_write(ctx, &i, sizeof(i)); + if (rv < 0) + return rv; + data = kmap(page[(addr - vma->vm_start) / PAGE_SIZE]); + rv = cr_write(ctx, data, 1 * PAGE_SIZE); + kunmap(page[(addr - vma->vm_start) / PAGE_SIZE]); + if (rv < 0) + return rv; + } + printk("dump vDSO: %08lx-%08lx, rv %d\n", vma->vm_start, vma->vm_end, rv); + return 0; +} + +static int cr_restore_vma_vdso(struct cr_context *ctx, loff_t pos) +{ + struct cr_image_vma_vdso *i; + int rv; + + i = kzalloc(sizeof(*i), GFP_KERNEL); + if (!i) + return -ENOMEM; + rv = cr_pread(ctx, i, sizeof(*i), pos); + if (rv < 0) { + kfree(i); + return rv; + } + if (i->cr_hdr.cr_type != CR_OBJ_VMA_VDSO) { + kfree(i); + return -EINVAL; + } + + rv = arch_setup_additional_pages(NULL, i->cr_vm_start, 0); + printk("restore vDSO: %08lx, rv %d\n", (unsigned long)i->cr_vm_start, rv); + kfree(i); + return rv; +} +#else +int special_mapping_checkpoint(struct vm_area_struct *vma, struct cr_context *ctx) +{ + return -EINVAL; +} + +static int cr_restore_vma_vdso(struct cr_context *ctx, loff_t pos) +{ + return -EINVAL; +} +#endif + static int cr_restore_all_vma(struct cr_context *ctx, loff_t pos) { struct cr_object_header cr_hdr; @@ -347,6 +429,11 @@ static int cr_restore_all_vma(struct cr_context *ctx, loff_t pos) if (rv < 0) return rv; break; + case CR_OBJ_VMA_VDSO: + rv = cr_restore_vma_vdso(ctx, pos); + if (rv < 0) + return rv; + break; case CR_OBJ_VMA_CONTENT: break; default: --- a/mm/mmap.c +++ b/mm/mmap.c @@ -2257,6 +2257,9 @@ static void special_mapping_close(struct vm_area_struct *vma) static struct vm_operations_struct special_mapping_vmops = { .close = special_mapping_close, .fault = special_mapping_fault, +#ifdef CONFIG_CR + .checkpoint = special_mapping_checkpoint, +#endif }; /* -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/