Prepare for a core file image.
This commit is contained in:
@@ -216,6 +216,8 @@ int gencore(struct process *proc, void *regs,
|
|||||||
unsigned int offset = 0;
|
unsigned int offset = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
*chunks = 3; /* Elf header , header table and NOTE segment */
|
||||||
|
|
||||||
if (vm == NULL) {
|
if (vm == NULL) {
|
||||||
dkprintf("no vm found.\n");
|
dkprintf("no vm found.\n");
|
||||||
return -1;
|
return -1;
|
||||||
@@ -226,11 +228,33 @@ int gencore(struct process *proc, void *regs,
|
|||||||
range->start, range->end, range->flag, range->objoff);
|
range->start, range->end, range->flag, range->objoff);
|
||||||
/* We omit reserved areas because they are only for
|
/* We omit reserved areas because they are only for
|
||||||
mckernel's internal use. */
|
mckernel's internal use. */
|
||||||
if ((range->flag & VR_RESERVED) != 0)
|
if (range->flag & VR_RESERVED)
|
||||||
continue;
|
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++;
|
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;
|
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 flag = range->flag;
|
||||||
unsigned long size = range->end - range->start;
|
unsigned long size = range->end - range->start;
|
||||||
|
|
||||||
if ((range->flag & VR_RESERVED) != 0)
|
if (range->flag & VR_RESERVED)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ph[i].p_type = PT_LOAD;
|
ph[i].p_type = PT_LOAD;
|
||||||
@@ -300,7 +324,7 @@ int gencore(struct process *proc, void *regs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* coretable to send to host */
|
/* 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) {
|
if (!ct) {
|
||||||
dkprintf("could not alloc a coretable.\n");
|
dkprintf("could not alloc a coretable.\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
@@ -320,14 +344,74 @@ int gencore(struct process *proc, void *regs,
|
|||||||
|
|
||||||
i = 3; /* memory segments */
|
i = 3; /* memory segments */
|
||||||
list_for_each_entry(range, &vm->vm_range_list, list) {
|
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;
|
continue;
|
||||||
ct[i].addr = virt_to_phys(range->start);
|
if (range->flag & VR_DEMAND_PAGING) {
|
||||||
ct[i].len = range->end - range->start;
|
/* Just an ad hoc kluge. */
|
||||||
dkprintf("coretable[%d]: %lx@%lx(%lx)\n", i, ct[i].len, ct[i].addr, range->start);
|
unsigned long p, start, phys;
|
||||||
i++;
|
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;
|
*coretable = ct;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -35,6 +35,8 @@
|
|||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include "mcctrl.h"
|
#include "mcctrl.h"
|
||||||
|
|
||||||
|
#define DEBUG 1
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define dprintk printk
|
#define dprintk printk
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -1180,7 +1180,7 @@ static int writecore(ihk_os_t os, unsigned long rcoretable, int chunks) {
|
|||||||
set_fs(KERNEL_DS);
|
set_fs(KERNEL_DS);
|
||||||
|
|
||||||
/* Every Linux documentation insists we should not
|
/* 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
|
* leads us here. Precisely, Here we emulate the core
|
||||||
* dump routine of the Linux kernel in linux/fs/exec.c.
|
* dump routine of the Linux kernel in linux/fs/exec.c.
|
||||||
* So we have a legitimate reason to do this.
|
* 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 */
|
/* map and write the chunk out */
|
||||||
rphys = coretable[i].addr;
|
rphys = coretable[i].addr;
|
||||||
size = coretable[i].len;
|
size = coretable[i].len;
|
||||||
dprintk("mapping remote %lx@%lx -> ", size, rphys);
|
if (rphys != 0) {
|
||||||
phys = ihk_device_map_memory(dev, rphys, size);
|
dprintk("mapping remote %x@%lx -> ", size, rphys);
|
||||||
dprintk("physical %lx, ", phys);
|
phys = ihk_device_map_memory(dev, rphys, size);
|
||||||
pt = ihk_device_map_virtual(dev, phys, size, NULL, 0);
|
dprintk("physical %lx, ", phys);
|
||||||
dprintk("virtual %lx\n", pt);
|
pt = ihk_device_map_virtual(dev, phys, size, NULL, 0);
|
||||||
if (pt != NULL) {
|
dprintk("virtual %p\n", pt);
|
||||||
ret = file->f_op->write(file, pt, size, &file->f_pos);
|
if (pt != NULL) {
|
||||||
} else {
|
ret = file->f_op->write(file, pt, size, &file->f_pos);
|
||||||
dprintk("cannot map physical memory(%lx) to virtual memory.\n",
|
} else {
|
||||||
phys);
|
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);
|
ihk_device_unmap_memory(dev, phys, size);
|
||||||
break;
|
} else {
|
||||||
}
|
/* We skip if the physical address is NULL
|
||||||
/* unmap the chunk */
|
and make the core file sparse. */
|
||||||
ihk_device_unmap_virtual(dev, pt, size);
|
if (!file->f_op->llseek || (file->f_op->llseek == no_llseek)) {
|
||||||
ihk_device_unmap_memory(dev, phys, size);
|
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) {
|
if (ret != size) {
|
||||||
dprintk("core file write failed(%d).\n", ret);
|
dprintk("core file write failed(%d).\n", ret);
|
||||||
error = PTR_ERR(file);
|
error = PTR_ERR(file);
|
||||||
|
|||||||
Reference in New Issue
Block a user