Fix for demand paging and documentation.

This commit is contained in:
Naoki Hamada
2014-07-23 10:23:02 +09:00
parent 9dd7d6283c
commit dbdaf0ed32
3 changed files with 89 additions and 13 deletions

View File

@@ -24,7 +24,12 @@
* of a chunk and its length. * of a chunk and its length.
*/ */
/* ELF header */ /**
* \brief Fill the elf header.
*
* \param eh An Elf64_Ehdr structure.
* \param segs Number of segments of the core file.
*/
void fill_elf_header(Elf64_Ehdr *eh, int segs) void fill_elf_header(Elf64_Ehdr *eh, int segs)
{ {
@@ -37,6 +42,8 @@ void fill_elf_header(Elf64_Ehdr *eh, int segs)
eh->e_ident[EI_VERSION] = El_VERSION; eh->e_ident[EI_VERSION] = El_VERSION;
eh->e_ident[EI_OSABI] = ELFOSABI_NONE; eh->e_ident[EI_OSABI] = ELFOSABI_NONE;
eh->e_ident[EI_ABIVERSION] = El_ABIVERSION_NONE; eh->e_ident[EI_ABIVERSION] = El_ABIVERSION_NONE;
memset((void *)eh + EI_PAD, 0, sizeof(*eh) - EI_PAD);
eh->e_type = ET_CORE; eh->e_type = ET_CORE;
#ifdef CONFIG_MIC #ifdef CONFIG_MIC
eh->e_machine = EM_K10M; eh->e_machine = EM_K10M;
@@ -56,7 +63,10 @@ void fill_elf_header(Elf64_Ehdr *eh, int segs)
eh->e_shstrndx = 0; eh->e_shstrndx = 0;
} }
/* prstatus NOTE */ /**
* \brief Return the size of the prstatus entry of the NOTE segment.
*
*/
int get_prstatus_size(void) int get_prstatus_size(void)
{ {
@@ -64,6 +74,14 @@ int get_prstatus_size(void)
+ align32(sizeof(struct elf_prstatus64)); + align32(sizeof(struct elf_prstatus64));
} }
/**
* \brief Fill a prstatus structure.
*
* \param head A pointer to a note structure.
* \param proc A pointer to the current process structure.
* \param regs0 A pointer to a x86_regs structure.
*/
void fill_prstatus(struct note *head, struct process *proc, void *regs0) void fill_prstatus(struct note *head, struct process *proc, void *regs0)
{ {
void *name; void *name;
@@ -80,6 +98,7 @@ void fill_prstatus(struct note *head, struct process *proc, void *regs0)
name = (void *) (head + 1); name = (void *) (head + 1);
memcpy(name, "CORE", sizeof("CORE")); memcpy(name, "CORE", sizeof("CORE"));
prstatus = (struct elf_prstatus64 *)(name + align32(sizeof("CORE"))); prstatus = (struct elf_prstatus64 *)(name + align32(sizeof("CORE")));
memset(prstatus, 0, sizeof(struct elf_prstatus64));
/* /*
We ignore following entries for now. We ignore following entries for now.
@@ -126,7 +145,10 @@ void fill_prstatus(struct note *head, struct process *proc, void *regs0)
prstatus->pr_fpvalid = 0; /* We assume no fp */ prstatus->pr_fpvalid = 0; /* We assume no fp */
} }
/* prpsinfo NOTE */ /**
* \brief Return the size of the prpsinfo entry of the NOTE segment.
*
*/
int get_prpsinfo_size(void) int get_prpsinfo_size(void)
{ {
@@ -134,6 +156,14 @@ int get_prpsinfo_size(void)
+ align32(sizeof(struct elf_prpsinfo64)); + align32(sizeof(struct elf_prpsinfo64));
} }
/**
* \brief Fill a prpsinfo structure.
*
* \param head A pointer to a note structure.
* \param proc A pointer to the current process structure.
* \param regs A pointer to a x86_regs structure.
*/
void fill_prpsinfo(struct note *head, struct process *proc, void *regs) void fill_prpsinfo(struct note *head, struct process *proc, void *regs)
{ {
void *name; void *name;
@@ -145,6 +175,7 @@ void fill_prpsinfo(struct note *head, struct process *proc, void *regs)
name = (void *) (head + 1); name = (void *) (head + 1);
memcpy(name, "CORE", sizeof("CORE")); memcpy(name, "CORE", sizeof("CORE"));
prpsinfo = (struct elf_prpsinfo64 *)(name + align32(sizeof("CORE"))); prpsinfo = (struct elf_prpsinfo64 *)(name + align32(sizeof("CORE")));
memset(prpsinfo, 0, sizeof(struct elf_prpsinfo64));
prpsinfo->pr_state = proc->status; prpsinfo->pr_state = proc->status;
prpsinfo->pr_pid = proc->pid; prpsinfo->pr_pid = proc->pid;
@@ -165,7 +196,10 @@ void fill_prpsinfo(struct note *head, struct process *proc, void *regs)
*/ */
} }
/* auxv NOTE */ /**
* \brief Return the size of the AUXV entry of the NOTE segment.
*
*/
int get_auxv_size(void) int get_auxv_size(void)
{ {
@@ -173,6 +207,14 @@ int get_auxv_size(void)
+ sizeof(unsigned long) * AUXV_LEN; + sizeof(unsigned long) * AUXV_LEN;
} }
/**
* \brief Fill an AUXV structure.
*
* \param head A pointer to a note structure.
* \param proc A pointer to the current process structure.
* \param regs A pointer to a x86_regs structure.
*/
void fill_auxv(struct note *head, struct process *proc, void *regs) void fill_auxv(struct note *head, struct process *proc, void *regs)
{ {
void *name; void *name;
@@ -187,7 +229,10 @@ void fill_auxv(struct note *head, struct process *proc, void *regs)
memcpy(auxv, proc->saved_auxv, sizeof(unsigned long) * AUXV_LEN); memcpy(auxv, proc->saved_auxv, sizeof(unsigned long) * AUXV_LEN);
} }
/* whole NOTE segment */ /**
* \brief Return the size of the whole NOTE segment.
*
*/
int get_note_size(void) int get_note_size(void)
{ {
@@ -195,6 +240,14 @@ int get_note_size(void)
+ get_auxv_size(); + get_auxv_size();
} }
/**
* \brief Fill the NOTE segment.
*
* \param head A pointer to a note structure.
* \param proc A pointer to the current process structure.
* \param regs A pointer to a x86_regs structure.
*/
void fill_note(void *note, struct process *proc, void *regs) void fill_note(void *note, struct process *proc, void *regs)
{ {
fill_prstatus(note, proc, regs); fill_prstatus(note, proc, regs);
@@ -204,7 +257,20 @@ void fill_note(void *note, struct process *proc, void *regs)
fill_auxv(note, proc, regs); fill_auxv(note, proc, regs);
} }
/* whole core image */ /**
* \brief Generate an image of the core file.
*
* \param proc A pointer to the current process structure.
* \param regs A pointer to a x86_regs structure.
* \param coretable(out) An array of core chunks.
* \param chunks(out) Number of the entires of coretable.
*
* A core chunk is represented by a pair of a physical
* address of memory region and its size. If there are
* no corresponding physical address for a VM area
* (an unallocated demand-paging page, e.g.), the address
* should be zero.
*/
int gencore(struct process *proc, void *regs, int gencore(struct process *proc, void *regs,
struct coretable **coretable, int *chunks) struct coretable **coretable, int *chunks)
@@ -430,7 +496,11 @@ int gencore(struct process *proc, void *regs,
return -1; return -1;
} }
/* Free all the allocated spaces. */ /**
* \brief Free all the allocated spaces for an image of the core file.
*
* \param coretable An array of core chunks.
*/
void freecore(struct coretable **coretable) void freecore(struct coretable **coretable)
{ {

View File

@@ -1215,6 +1215,11 @@ static int writecore(ihk_os_t os, unsigned long rcoretable, int chunks) {
/* unmap the chunk */ /* unmap the chunk */
ihk_device_unmap_virtual(dev, pt, size); ihk_device_unmap_virtual(dev, pt, size);
ihk_device_unmap_memory(dev, phys, size); ihk_device_unmap_memory(dev, phys, size);
if (ret != size) {
dprintk("core file write failed(%d).\n", ret);
error = PTR_ERR(file);
break;
}
} else { } else {
/* We skip if the physical address is NULL /* We skip if the physical address is NULL
and make the core file sparse. */ and make the core file sparse. */
@@ -1229,11 +1234,6 @@ static int writecore(ihk_os_t os, unsigned long rcoretable, int chunks) {
break; break;
} }
} }
if (ret != size) {
dprintk("core file write failed(%d).\n", ret);
error = PTR_ERR(file);
break;
}
} }
/* unmap the chunk table */ /* unmap the chunk table */
ihk_device_unmap_virtual(dev, coretable, tablesize); ihk_device_unmap_virtual(dev, coretable, tablesize);

View File

@@ -169,9 +169,15 @@ void check_signal(unsigned long rc, void *regs);
int gencore(struct process *, void *, struct coretable **, int *); int gencore(struct process *, void *, struct coretable **, int *);
void freecore(struct coretable **); void freecore(struct coretable **);
/**
* \brief Generate a core file and tell the host to write it out.
*
* \param proc A current process structure.
* \param regs A pointer to a x86_regs structure.
*/
static void coredump(struct process *proc, void *regs) static void coredump(struct process *proc, void *regs)
{ {
/* xxx */
struct syscall_request request IHK_DMA_ALIGN; struct syscall_request request IHK_DMA_ALIGN;
int ret; int ret;
struct coretable *coretable; struct coretable *coretable;