Merge branch 'master' of postpeta.pccluster.org:mckernel

This commit is contained in:
Naoki Hamada
2014-09-05 17:20:50 +09:00
10 changed files with 363 additions and 142 deletions

View File

@ -63,6 +63,8 @@ struct program_image_section {
void *fp;
};
#define SHELL_PATH_MAX_LEN 1024
struct program_load_desc {
int num_sections;
int status;
@ -88,6 +90,7 @@ struct program_load_desc {
unsigned long rlimit_stack_cur;
unsigned long rlimit_stack_max;
unsigned long interp_align;
char shell_path[SHELL_PATH_MAX_LEN];
struct program_image_section sections[0];
};

View File

@ -284,7 +284,7 @@ static long mcexec_send_signal(ihk_os_t os, struct signal_desc *sigparam)
isp.pid = sig.pid;
isp.arg = (long)sig.tid << 32 | (sig.sig & 0x00000000ffffffffL);
mcctrl_ikc_send(os, 0, &isp);
mcctrl_ikc_send(os, sig.cpu, &isp);
return 0;
}

View File

@ -405,6 +405,25 @@ static int rus_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
pfn = phys >> PAGE_SHIFT;
#if USE_VM_INSERT_PFN
for (pix = 0; pix < (pgsize / PAGE_SIZE); ++pix) {
struct page *page;
if (pfn_valid(pfn+pix)) {
page = pfn_to_page(pfn+pix);
if (!page_count(page)) {
get_page(page);
/*
* TODO:
* The pages which get_page() has been called with
* should be recorded. Because these pages have to
* be passed to put_page() before they are freed.
*/
}
error = vm_insert_page(vma, rva+(pix*PAGE_SIZE), page);
if (error) {
printk("vm_insert_page: %d\n", error);
}
}
else
error = vm_insert_pfn(vma, rva+(pix*PAGE_SIZE), pfn+pix);
if (error) {
break;
@ -429,7 +448,7 @@ static struct vm_operations_struct rus_vmops = {
static int rus_mmap(struct file *file, struct vm_area_struct *vma)
{
vma->vm_flags |= VM_IO | VM_RESERVED | VM_DONTEXPAND | VM_PFNMAP;
vma->vm_flags |= VM_RESERVED | VM_DONTEXPAND | VM_MIXEDMAP;
vma->vm_ops = &rus_vmops;
return 0;
}
@ -1125,13 +1144,16 @@ out:
return (IS_ERR_VALUE(map))? (int)map: 0;
}
static void clear_pte_range(uintptr_t start, uintptr_t len)
static int clear_pte_range(uintptr_t start, uintptr_t len)
{
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
uintptr_t addr;
uintptr_t end;
int error;
int ret;
ret = 0;
down_read(&mm->mmap_sem);
addr = start;
while (addr < (start + len)) {
@ -1148,14 +1170,15 @@ static void clear_pte_range(uintptr_t start, uintptr_t len)
end = vma->vm_end;
}
if (addr < end) {
zap_vma_ptes(vma, addr, end-addr);
dprintk("clear_pte_range() 0x%lx - 0x%lx OK\n",
vma->vm_start, vma->vm_end);
error = zap_vma_ptes(vma, addr, end-addr);
if (ret == 0) {
ret = error;
}
}
addr = end;
}
up_read(&mm->mmap_sem);
return;
return ret;
}
/**
@ -1293,7 +1316,11 @@ int __do_in_kernel_syscall(ihk_os_t os, struct mcctrl_channel *c, struct syscall
ppd->pid, ppd->rpgtable);
}
clear_pte_range(sc->args[0], sc->args[1]);
error = clear_pte_range(sc->args[0], sc->args[1]);
if (error) {
error = -ENOSYS;
goto out;
}
ret = 0;
break;

View File

@ -338,14 +338,144 @@ struct program_load_desc *load_interp(struct program_load_desc *desc0, FILE *fp)
unsigned char *dma_buf;
int load_elf_desc(char *filename, struct program_load_desc **desc_p)
int lookup_exec_path(char *filename, char *path, int max_len)
{
int found;
int error;
struct stat sb;
char *link_path = NULL;
retry:
found = 0;
/* Is file not absolute path? */
if (strncmp(filename, "/", 1)) {
/* Is filename a single component without path? */
if (strncmp(filename, ".", 1) && !strchr(filename, '/')) {
char *token, *string, *tofree;
char *PATH = getenv("COKERNEL_PATH");
if (!PATH) {
PATH = getenv("PATH");
}
if (strlen(filename) >= 255) {
return ENAMETOOLONG;
}
__dprintf("PATH: %s\n", PATH);
/* strsep() modifies string! */
tofree = string = strdup(PATH);
if (string == NULL) {
printf("lookup_exec_path(): copying PATH, not enough memory?\n");
return ENOMEM;
}
while ((token = strsep(&string, ":")) != NULL) {
error = snprintf(path, max_len,
"%s/%s", token, filename);
if (error < 0 || error >= max_len) {
fprintf(stderr, "lookup_exec_path(): array too small?\n");
continue;
}
error = access(path, X_OK);
if (error == 0) {
found = 1;
break;
}
}
free(tofree);
}
/* Not in path, file to be open from the working directory */
if (!found) {
error = snprintf(path, max_len, "%s", filename);
if (error < 0 || error >= max_len) {
fprintf(stderr, "lookup_exec_path(): array too small?\n");
return ENOMEM;
}
found = 1;
}
}
/* Absolute path */
else if (!strncmp(filename, "/", 1)) {
char *root = getenv("COKERNEL_EXEC_ROOT");
if (root) {
error = snprintf(path, max_len, "%s/%s", root, filename);
}
else {
error = snprintf(path, max_len, "%s", filename);
}
if (error < 0 || error >= max_len) {
fprintf(stderr, "lookup_exec_path(): array too small?\n");
return ENOMEM;
}
found = 1;
}
if (link_path) {
free(link_path);
link_path = NULL;
}
/* Check whether the resolved path is a symlink */
if (lstat(path, &sb) == -1) {
fprintf(stderr, "lookup_exec_path(): error stat\n");
return errno;
}
if ((sb.st_mode & S_IFMT) == S_IFLNK) {
char *link_path = malloc(max_len);
if (!link_path) {
fprintf(stderr, "lookup_exec_path(): error allocating\n");
return ENOMEM;
}
error = readlink(path, link_path, max_len);
if (error == -1 || error == max_len) {
fprintf(stderr, "lookup_exec_path(): error readlink\n");
return EINVAL;
}
__dprintf("lookup_exec_path(): %s is link -> %s\n", path, link_path);
filename = link_path;
goto retry;
}
if (!found) {
fprintf(stderr,
"lookup_exec_path(): error finding file %s\n", filename);
return ENOENT;
}
__dprintf("lookup_exec_path(): %s\n", path);
return 0;
}
int load_elf_desc(char *filename, struct program_load_desc **desc_p,
char **shell_p)
{
FILE *fp;
FILE *interp = NULL;
char *interp_path;
char *shell = NULL;
size_t shell_len = 0;
struct program_load_desc *desc;
int ret = 0;
struct stat sb;
char header[1024];
if ((ret = access(filename, X_OK)) != 0) {
fprintf(stderr, "Error: %s is not an executable?, errno: %d\n",
@ -369,6 +499,27 @@ int load_elf_desc(char *filename, struct program_load_desc **desc_p)
return errno;
}
if (fread(&header, 1, 2, fp) != 2) {
fprintf(stderr, "Error: Failed to read header from %s\n", filename);
return errno;
}
if (!strncmp(header, "#!", 2)) {
if (getline(&shell, &shell_len, fp) == -1) {
fprintf(stderr, "Error: reading shell path %s\n", filename);
}
fclose(fp);
/* Delete new line character */
shell[strlen(shell) - 1] = 0;
*shell_p = shell;
return 0;
}
rewind(fp);
desc = load_elf(fp, &interp_path);
if (!desc) {
fclose(fp);
@ -519,7 +670,7 @@ void print_flat(char *flat)
* returns the total length of the flat string and updates flat to
* point to the beginning.
*/
int flatten_strings(int nr_strings, char **strings, char **flat)
int flatten_strings(int nr_strings, char *first, char **strings, char **flat)
{
int full_len, string_i;
unsigned long flat_offset;
@ -532,6 +683,10 @@ int flatten_strings(int nr_strings, char **strings, char **flat)
/* Count full length */
full_len = sizeof(int) + sizeof(char *); // Counter and terminating NULL
if (first) {
full_len += sizeof(char *) + strlen(first) + 1;
}
for (string_i = 0; string_i < nr_strings; ++string_i) {
// Pointer + actual value
full_len += sizeof(char *) + strlen(strings[string_i]) + 1;
@ -545,18 +700,25 @@ int flatten_strings(int nr_strings, char **strings, char **flat)
memset(_flat, 0, full_len);
/* Number of strings */
*((int*)_flat) = nr_strings;
*((int*)_flat) = nr_strings + (first ? 1 : 0);
// Actual offset
flat_offset = sizeof(int) + sizeof(char *) * (nr_strings + 1);
flat_offset = sizeof(int) + sizeof(char *) * (nr_strings + 1 +
(first ? 1 : 0));
if (first) {
*((char **)(_flat + sizeof(int))) = (void *)flat_offset;
memcpy(_flat + flat_offset, first, strlen(first) + 1);
flat_offset += strlen(first) + 1;
}
for (string_i = 0; string_i < nr_strings; ++string_i) {
/* Fabricate the string */
*((char **)(_flat + sizeof(int) + string_i * sizeof(char *))) = (void *)flat_offset;
*((char **)(_flat + sizeof(int) + (string_i + (first ? 1 : 0))
* sizeof(char *))) = (void *)flat_offset;
memcpy(_flat + flat_offset, strings[string_i], strlen(strings[string_i]) + 1);
flat_offset += strlen(strings[string_i]) + 1;
}
*flat = _flat;
@ -609,33 +771,27 @@ sendsig(int sig, siginfo_t *siginfo, void *context)
siginfo->si_signo == SIGINT)
return;
if(tid == master_tid){
cpu = 0;
remote_tid = -1;
for(i = 0; i < ncpu; i++){
if(siginfo->si_pid == pid &&
thread_data[i].tid == tid){
if(thread_data[i].terminate)
return;
break;
}
if(siginfo->si_pid != pid &&
thread_data[i].remote_tid == tid){
if(thread_data[i].terminate)
return;
break;
}
}
if(i != ncpu){
remote_tid = thread_data[i].remote_tid;
cpu = thread_data[i].cpu;
}
else{
for(i = 1; i < ncpu; i++){
if(siginfo->si_pid == pid &&
thread_data[i].tid == tid){
if(thread_data[i].terminate)
return;
break;
}
if(siginfo->si_pid != pid &&
thread_data[i].remote_tid == tid){
if(thread_data[i].terminate)
return;
break;
}
}
if(i != ncpu){
remote_tid = thread_data[i].remote_tid;
cpu = thread_data[i].cpu;
}
else{
cpu = 0;
remote_tid = -1;
}
cpu = 0;
remote_tid = -1;
}
sigdesc.cpu = cpu;
@ -764,6 +920,9 @@ int main(int argc, char **argv)
int target_core = 0;
int mcosid = 0;
int opt;
char path[1024];
char *shell = NULL;
char shell_path[1024];
#ifdef USE_SYSCALL_MOD_CALL
__glob_argc = argc;
@ -776,7 +935,7 @@ int main(int argc, char **argv)
}
/* Collect environment variables */
envs_len = flatten_strings(-1, environ, &envs);
envs_len = flatten_strings(-1, NULL, environ, &envs);
envs = envs;
error = getrlimit(RLIMIT_STACK, &rlim_stack);
@ -828,18 +987,40 @@ int main(int argc, char **argv)
for (i = optind; i < argc; ++i) {
__dprintf("%s ", argv[i]);
}
__dprintf("\n");
__dprintf("%s", "\n");
if (load_elf_desc(argv[optind], &desc) != 0) {
if (lookup_exec_path(argv[optind], path, sizeof(path)) != 0) {
fprintf(stderr, "error: finding file: %s\n", argv[optind]);
return 1;
}
if (load_elf_desc(path, &desc, &shell) != 0) {
fprintf(stderr, "error: loading file: %s\n", argv[optind]);
return 1;
}
/* Check whether shell script */
if (shell) {
if (lookup_exec_path(shell, shell_path, sizeof(shell_path)) != 0) {
fprintf(stderr, "error: finding file: %s\n", shell);
return 1;
}
if (load_elf_desc(shell_path, &desc, &shell) != 0) {
fprintf(stderr, "error: loading file: %s\n", shell);
return 1;
}
}
if (shell) {
argv[optind] = path;
}
desc->envs_len = envs_len;
desc->envs = envs;
//print_flat(envs);
desc->args_len = flatten_strings(-1, argv + optind, &args);
desc->args_len = flatten_strings(-1, shell, argv + optind, &args);
desc->args = args;
//print_flat(args);
@ -1168,12 +1349,17 @@ int main_loop(int fd, int cpu, pthread_mutex_t *lock, int mcosid)
return w.sr.args[0];
case __NR_mmap:
case __NR_munmap:
case __NR_mprotect:
/* reserved for internal use */
do_syscall_return(fd, cpu, -ENOSYS, 0, 0, 0, 0);
break;
case __NR_munmap:
ret = madvise((void *)w.sr.args[0], w.sr.args[1], MADV_DONTNEED);
SET_ERR(ret);
do_syscall_return(fd, cpu, ret, 0, 0, 0, 0);
break;
#ifdef USE_SYSCALL_MOD_CALL
case 303:{
__dprintf("mcexec.c,mod_cal,mod=%ld,cmd=%ld\n", w.sr.args[0], w.sr.args[1]);
@ -1271,93 +1457,51 @@ int main_loop(int fd, int cpu, pthread_mutex_t *lock, int mcosid)
switch (w.sr.args[0]) {
struct program_load_desc *desc;
struct remote_transfer trans;
int error;
int found;
char path[2048];
char path[1024];
char *filename;
int ret;
char *shell = NULL;
char shell_path[1024];
/* Load descriptor phase */
case 1:
ret = -1;
found = 0;
filename = (char *)w.sr.args[1];
/* Is filename a single component without path? */
if (strncmp(filename, "/", 1)
&& !strchr(filename, '/')) {
char *token, *string, *tofree;
char *PATH = getenv("COKERNEL_PATH");
if (!PATH) {
PATH = getenv("PATH");
}
if (strlen(filename) >= 255) {
ret = ENAMETOOLONG;
goto return_execve1;
}
__dprintf("PATH: %s\n", PATH);
/* strsep() modifies string! */
tofree = string = strdup(PATH);
if (string == NULL) {
printf("error: copying PATH, not enough memory?\n");
goto return_execve1;
}
while ((token = strsep(&string, ":")) != NULL) {
error = snprintf(path, sizeof(path),
"%s/%s", token, filename);
if (error < 0 || error >= sizeof(path)) {
fprintf(stderr, "execve(): array too small?\n");
continue;
}
error = access(path, X_OK);
if (error == 0) {
found = 1;
break;
}
}
free(tofree);
}
else {
char *root = getenv("COKERNEL_EXEC_ROOT");
if (root) {
error = snprintf(path, sizeof(path), "%s/%s", root, filename);
}
else {
error = snprintf(path, sizeof(path), "%s", filename);
}
if (error < 0 || error >= sizeof(path)) {
fprintf(stderr, "execve(): array too small?\n");
goto return_execve1;
}
found = 1;
}
if (!found) {
fprintf(stderr,
"execve(): error finding file %s\n", filename);
ret = ENOENT;
if ((ret = lookup_exec_path(filename, path, sizeof(path)))
!= 0) {
goto return_execve1;
}
__dprintf("execve(): path to binary: %s\n", path);
if ((ret = load_elf_desc(path, &desc)) != 0) {
if ((ret = load_elf_desc(path, &desc, &shell)) != 0) {
fprintf(stderr,
"execve(): error loading ELF for file %s\n", path);
goto return_execve1;
}
/* Check whether shell script */
if (shell) {
if ((ret = lookup_exec_path(shell, shell_path,
sizeof(shell_path))) != 0) {
fprintf(stderr, "execve(): error: finding file: %s\n", shell);
goto return_execve1;
}
if ((ret = load_elf_desc(shell_path, &desc, &shell))
!= 0) {
fprintf(stderr, "execve(): error: loading file: %s\n", shell);
goto return_execve1;
}
if (strlen(shell_path) >= SHELL_PATH_MAX_LEN) {
fprintf(stderr, "execve(): error: shell path too long: %s\n", shell_path);
ret = ENAMETOOLONG;
goto return_execve1;
}
/* Let the LWK know the shell interpreter */
strcpy(desc->shell_path, shell_path);
}
__dprintf("execve(): load_elf_desc() for %s OK, num sections: %d\n",
path, desc->num_sections);
@ -1412,10 +1556,10 @@ return_execve1:
goto return_execve1;
}
__dprintf("execve(): transfer ELF desc OK\n");
__dprintf("%s", "execve(): transfer ELF desc OK\n");
transfer_image(fd, desc);
__dprintf("execve(): image transferred\n");
__dprintf("%s", "execve(): image transferred\n");
ret = 0;
return_execve2: