From 3e8083efc1793cd482b5de70397c7d8e2ac0300e Mon Sep 17 00:00:00 2001 From: Naoki Hamada Date: Thu, 17 Jul 2014 15:19:25 +0900 Subject: [PATCH] Prepare for a core file image. --- arch/x86/kernel/gencore.c | 104 ++++++++++++++++++++++++++++++++++---- executer/kernel/control.c | 2 + executer/kernel/syscall.c | 47 +++++++++++------ 3 files changed, 127 insertions(+), 26 deletions(-) diff --git a/arch/x86/kernel/gencore.c b/arch/x86/kernel/gencore.c index 72a3b547..a8b2e150 100644 --- a/arch/x86/kernel/gencore.c +++ b/arch/x86/kernel/gencore.c @@ -216,6 +216,8 @@ int gencore(struct process *proc, void *regs, unsigned int offset = 0; int i; + *chunks = 3; /* Elf header , header table and NOTE segment */ + if (vm == NULL) { dkprintf("no vm found.\n"); return -1; @@ -226,11 +228,33 @@ int gencore(struct process *proc, void *regs, range->start, range->end, range->flag, range->objoff); /* We omit reserved areas because they are only for mckernel's internal use. */ - if ((range->flag & VR_RESERVED) != 0) + if (range->flag & VR_RESERVED) continue; + /* We need a chunk for each page for a demand paging area. + This can be optimized for spacial complexity but we would + lose simplicity instead. */ + if (range->flag & VR_DEMAND_PAGING) { + unsigned long p, phys; + int prevzero = 0; + for (p = range->start; p < range->end; p += PAGE_SIZE) { + if (ihk_mc_pt_virt_to_phys(proc->vm->page_table, + (void *)p, &phys) != 0) { + prevzero = 1; + } else { + if (prevzero == 1) + (*chunks)++; + (*chunks)++; + prevzero = 0; + } + } + if (prevzero == 1) + (*chunks)++; + } else { + (*chunks)++; + } segs++; } - dkprintf("we have %d segs including one for NOTE.\n\n", segs); + dkprintf("we have %d segs and %d chunks.\n\n", segs, *chunks); { struct vm_regions region = proc->vm->region; @@ -282,7 +306,7 @@ int gencore(struct process *proc, void *regs, unsigned long flag = range->flag; unsigned long size = range->end - range->start; - if ((range->flag & VR_RESERVED) != 0) + if (range->flag & VR_RESERVED) continue; ph[i].p_type = PT_LOAD; @@ -300,7 +324,7 @@ int gencore(struct process *proc, void *regs, } /* coretable to send to host */ - ct = kmalloc(sizeof(struct coretable) * (segs + 2), IHK_MC_AP_NOWAIT); + ct = kmalloc(sizeof(struct coretable) * (*chunks), IHK_MC_AP_NOWAIT); if (!ct) { dkprintf("could not alloc a coretable.\n"); goto fail; @@ -320,14 +344,74 @@ int gencore(struct process *proc, void *regs, i = 3; /* memory segments */ list_for_each_entry(range, &vm->vm_range_list, list) { - if ((range->flag & VR_RESERVED) != 0) + unsigned long phys; + + if (range->flag & VR_RESERVED) continue; - ct[i].addr = virt_to_phys(range->start); - ct[i].len = range->end - range->start; - dkprintf("coretable[%d]: %lx@%lx(%lx)\n", i, ct[i].len, ct[i].addr, range->start); - i++; + if (range->flag & VR_DEMAND_PAGING) { + /* Just an ad hoc kluge. */ + unsigned long p, start, phys; + int prevzero = 0; + unsigned long size = 0; + + for (start = p = range->start; + p < range->end; p += PAGE_SIZE) { + if (ihk_mc_pt_virt_to_phys(proc->vm->page_table, + (void *)p, &phys) != 0) { + if (prevzero == 0) { + /* We begin a new chunk */ + size = PAGE_SIZE; + start = p; + } else { + /* We extend the previous chunk */ + size += PAGE_SIZE; + } + prevzero = 1; + } else { + if (prevzero == 1) { + /* Flush out an empty chunk */ + ct[i].addr = 0; + ct[i].len = size; + dkprintf("coretable[%d]: %lx@%lx(%lx)\n", i, + ct[i].len, ct[i].addr, start); + i++; + + } + ct[i].addr = phys; + ct[i].len = PAGE_SIZE; + dkprintf("coretable[%d]: %lx@%lx(%lx)\n", i, + ct[i].len, ct[i].addr, p); + i++; + prevzero = 0; + } + } + if (prevzero == 1) { + /* An empty chunk */ + ct[i].addr = 0; + ct[i].len = size; + dkprintf("coretable[%d]: %lx@%lx(%lx)\n", i, + ct[i].len, ct[i].addr, start); + i++; + } + } else { + if ((proc->vm->region.user_start <= range->start) && + (range->end <= proc->vm->region.user_end)) { + if (ihk_mc_pt_virt_to_phys(proc->vm->page_table, + (void *)range->start, &phys) != 0) { + dkprintf("could not convert user virtual address %lx" + "to physical address", range->start); + goto fail; + } + } else { + phys = virt_to_phys((void *)range->start); + } + ct[i].addr = phys; + ct[i].len = range->end - range->start; + dkprintf("coretable[%d]: %lx@%lx(%lx)\n", i, + ct[i].len, ct[i].addr, range->start); + i++; + } } - *chunks = segs + 2; *coretable = ct; return 0; diff --git a/executer/kernel/control.c b/executer/kernel/control.c index 4b0c837d..aa34a436 100644 --- a/executer/kernel/control.c +++ b/executer/kernel/control.c @@ -35,6 +35,8 @@ #include #include "mcctrl.h" +#define DEBUG 1 + #ifdef DEBUG #define dprintk printk #else diff --git a/executer/kernel/syscall.c b/executer/kernel/syscall.c index fcb56e8f..4250375c 100644 --- a/executer/kernel/syscall.c +++ b/executer/kernel/syscall.c @@ -1180,7 +1180,7 @@ static int writecore(ihk_os_t os, unsigned long rcoretable, int chunks) { set_fs(KERNEL_DS); /* Every Linux documentation insists we should not - * open a file in the kernel module, but our karma makes + * open a file in the kernel module, but our karma * leads us here. Precisely, Here we emulate the core * dump routine of the Linux kernel in linux/fs/exec.c. * So we have a legitimate reason to do this. @@ -1200,22 +1200,37 @@ static int writecore(ihk_os_t os, unsigned long rcoretable, int chunks) { /* map and write the chunk out */ rphys = coretable[i].addr; size = coretable[i].len; - dprintk("mapping remote %lx@%lx -> ", size, rphys); - phys = ihk_device_map_memory(dev, rphys, size); - dprintk("physical %lx, ", phys); - pt = ihk_device_map_virtual(dev, phys, size, NULL, 0); - dprintk("virtual %lx\n", pt); - if (pt != NULL) { - ret = file->f_op->write(file, pt, size, &file->f_pos); - } else { - dprintk("cannot map physical memory(%lx) to virtual memory.\n", - phys); + if (rphys != 0) { + dprintk("mapping remote %x@%lx -> ", size, rphys); + phys = ihk_device_map_memory(dev, rphys, size); + dprintk("physical %lx, ", phys); + pt = ihk_device_map_virtual(dev, phys, size, NULL, 0); + dprintk("virtual %p\n", pt); + if (pt != NULL) { + ret = file->f_op->write(file, pt, size, &file->f_pos); + } else { + dprintk("cannot map physical memory(%lx) to virtual memory.\n", + phys); + ihk_device_unmap_memory(dev, phys, size); + break; + } + /* unmap the chunk */ + ihk_device_unmap_virtual(dev, pt, size); ihk_device_unmap_memory(dev, phys, size); - break; - } - /* unmap the chunk */ - ihk_device_unmap_virtual(dev, pt, size); - ihk_device_unmap_memory(dev, phys, size); + } else { + /* We skip if the physical address is NULL + and make the core file sparse. */ + if (!file->f_op->llseek || (file->f_op->llseek == no_llseek)) { + dprintk("We have no llseek. The core file is truncated.\n"); + error = -EINVAL; + } + ret = file->f_op->llseek(file, size, SEEK_CUR); + if (ret < 0) { + dprintk("core file seek failed(%d).\n", ret); + error = PTR_ERR(file); + break; + } + } if (ret != size) { dprintk("core file write failed(%d).\n", ret); error = PTR_ERR(file);