From b59be07e9a558dd5a8907d089e2b96f01dc3cf0a Mon Sep 17 00:00:00 2001 From: "Masamichi Takagi m-takagi@ab.jp.nec.com" Date: Tue, 2 Jul 2013 21:31:38 +0900 Subject: [PATCH] implementing demand paging to make it possible to run Intel OpenMP programs --- kernel/include/process.h | 3 ++- kernel/mem.c | 31 +++++++++++++++++++++++++++++++ kernel/process.c | 31 +++++++++++++++++++++++++------ kernel/syscall.c | 24 +++++++++++++++++++++--- 4 files changed, 79 insertions(+), 10 deletions(-) diff --git a/kernel/include/process.h b/kernel/include/process.h index 4d12eaa3..1a4b2690 100644 --- a/kernel/include/process.h +++ b/kernel/include/process.h @@ -12,6 +12,7 @@ #define VR_RESERVED 0x2 #define VR_IO_NOCACHE 0x100 #define VR_REMOTE 0x200 +#define VR_DEMAND_PAGING 0x1000 #define PS_RUNNING 0x1 #define PS_INTERRUPTIBLE 0x2 @@ -22,7 +23,7 @@ #define PS_NORMAL (PS_INTERRUPTIBLE | PS_UNINTERRUPTIBLE) #ifdef ATTACHED_MIC -#define USE_LARGE_PAGES +//#define USE_LARGE_PAGES #endif #include diff --git a/kernel/mem.c b/kernel/mem.c index 57b67853..5dc7bf06 100644 --- a/kernel/mem.c +++ b/kernel/mem.c @@ -110,6 +110,36 @@ static void page_fault_handler(unsigned long address, void *regs, if (range->start <= address && range->end > address) { __kprintf("address is in range, flag: 0x%X! \n", range->flag); + if(range->flag & VR_DEMAND_PAGING){ + //allocate page for demand paging + __kprintf("demand paging\n"); + void* pa = allocate_pages(1, IHK_MC_AP_CRITICAL); + if(!pa){ + kprintf_unlock(irqflags); + panic("allocate_pages failed"); + } + __kprintf("physical memory area obtained %lx\n", virt_to_phys(pa)); + + { + enum ihk_mc_pt_attribute flag = 0; + struct process *process = cpu_local_var(current); + unsigned long flags = ihk_mc_spinlock_lock(&process->vm->page_table_lock); + const enum ihk_mc_pt_attribute attr = flag | PTATTR_WRITABLE | PTATTR_USER | PTATTR_FOR_USER; + + int rc = ihk_mc_pt_set_page(process->vm->page_table, (void*)(address & PAGE_MASK), virt_to_phys(pa), attr); + if(rc != 0) { + ihk_mc_spinlock_unlock(&process->vm->page_table_lock, flags); + __kprintf("ihk_mc_pt_set_page failed,rc=%d,%p,%lx,%08x\n", rc, (void*)(address & PAGE_MASK), virt_to_phys(pa), attr); + ihk_mc_pt_print_pte(process->vm->page_table, (void*)address); + goto fn_fail; + } + ihk_mc_spinlock_unlock(&process->vm->page_table_lock, flags); + __kprintf("update_process_page_table success\n"); + } + kprintf_unlock(irqflags); + memset(pa, 0, PAGE_SIZE); + return; + } found = 1; ihk_mc_pt_print_pte(cpu_local_var(current)->vm->page_table, (void*)address); @@ -120,6 +150,7 @@ static void page_fault_handler(unsigned long address, void *regs, if (!found) __kprintf("address is out of range! \n"); + fn_fail: kprintf_unlock(irqflags); /* TODO */ diff --git a/kernel/process.c b/kernel/process.c index 26499f00..82418060 100644 --- a/kernel/process.c +++ b/kernel/process.c @@ -103,7 +103,7 @@ struct process *clone_process(struct process *org, unsigned long pc, extern void __host_update_process_range(struct process *process, struct vm_range *range); -static int update_process_page_table(struct process *process, +int update_process_page_table(struct process *process, struct vm_range *range, enum ihk_mc_pt_attribute flag) { unsigned long p, pa = range->phys; @@ -239,14 +239,18 @@ int remove_process_memory_range(struct process *process, unsigned long start, un range->end = start; } - if (freesize > 0) { + /* FIXME: traverse page table entries and release physical memory area if present + then mark the page table entry non-present */ + if (freesize > 0 && !(range->flag & VR_DEMAND_PAGING)) { + dkprintf("remove_process_memory_range,remove_process_region\n"); error = remove_process_region(process, freestart, (freestart + freesize)); if (error) { kprintf("remove_process_memory_range:remove_process_region failed: %d\n", error); /* through */ } - if (!(range->flag & (VR_REMOTE | VR_IO_NOCACHE | VR_RESERVED))) { + if (!(range->flag & (VR_REMOTE | VR_IO_NOCACHE | VR_RESERVED)) && !(range->flag & VR_DEMAND_PAGING)) { + dkprintf("remove_process_memory_range,ihk_mc_free_pages\n"); // XXX: need TLB shootdown? ihk_mc_free_pages(phys_to_virt(freephys), freesize>>PAGE_SHIFT); } @@ -287,14 +291,23 @@ int add_process_memory_range(struct process *process, range->phys = phys; range->flag = flag; + if(range->flag & VR_DEMAND_PAGING) { + dkprintf("range: 0x%lX - 0x%lX => physicall memory area is allocated on demand (%ld)\n", + range->start, range->end, range->end - range->start); + } else { dkprintf("range: 0x%lX - 0x%lX => 0x%lX - 0x%lX (%ld)\n", range->start, range->end, range->phys, range->phys + range->end - range->start, range->end - range->start); + } if (flag & VR_REMOTE) { rc = update_process_page_table(process, range, IHK_PTA_REMOTE); } else if (flag & VR_IO_NOCACHE) { rc = update_process_page_table(process, range, PTATTR_UNCACHABLE); + } else if(flag & VR_DEMAND_PAGING){ + //demand paging no need to update process table now + kprintf("demand paging do not update process page table\n"); + rc = 0; } else { rc = update_process_page_table(process, range, 0); } @@ -312,7 +325,7 @@ int add_process_memory_range(struct process *process, list_add_tail(&range->list, &process->vm->vm_range_list); /* Clear content! */ - if (!(flag & VR_REMOTE)) + if (!(flag & VR_REMOTE) && !(flag & VR_DEMAND_PAGING)) memset((void*)phys_to_virt(range->phys), 0, end - start); return 0; @@ -396,6 +409,7 @@ unsigned long extend_process_region(struct process *proc, #ifdef USE_LARGE_PAGES if (aligned_new_end - aligned_end >= LARGE_PAGE_SIZE) { + if(flag & VR_DEMAND_PAGING){panic("demand paging for large page is not available!");} unsigned long p_aligned; unsigned long old_aligned_end = aligned_end; @@ -452,15 +466,20 @@ unsigned long extend_process_region(struct process *proc, return address; } #endif + if(flag & VR_DEMAND_PAGING){ + // demand paging no need to allocate page now + kprintf("demand page do not allocate page\n"); + p=0; + }else{ p = allocate_pages((aligned_new_end - aligned_end) >> PAGE_SHIFT, IHK_MC_AP_NOWAIT); if (!p) { return end; } - + } if((rc = add_process_memory_range(proc, aligned_end, aligned_new_end, - virt_to_phys(p), flag)) != 0){ + (p==0?0:virt_to_phys(p)), flag)) != 0){ free_pages(p, (aligned_new_end - aligned_end) >> PAGE_SHIFT); return end; } diff --git a/kernel/syscall.c b/kernel/syscall.c index b0e7f953..e0bdb614 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -274,7 +274,21 @@ SYSCALL_DECLARE(mmap) unsigned long s = (region->map_end + PAGE_SIZE - 1) & PAGE_MASK; unsigned long map_end_aligned = region->map_end; unsigned long len = (ihk_mc_syscall_arg1(ctx) + PAGE_SIZE - 1) & PAGE_MASK; - dkprintf("syscall.c,mmap,len=%lx", len); + dkprintf("syscall.c,mmap,len=%lx\n", len); + + unsigned long flag = 0; /* eager paging */ +#if 1 + /* Intel OpenMP hack: it requests 128MB and munmap tail and head + to create 64MB-aligned 64MB memory area + and then it tries to touch memory-block + with offset of 0x10, 0x101008 */ + if(ihk_mc_syscall_arg1(ctx) == 1024*1024*64 || ihk_mc_syscall_arg1(ctx) == 1024*1024*128) { + flag |= VR_DEMAND_PAGING; /* demand paging */ + kprintf("SC(%d)[mmap],!MAP_FIXED,MAP_ANONYMOUS,sz=%lx\n", ihk_mc_get_processor_id(), ihk_mc_syscall_arg1(ctx)); + } + //if(ihk_mc_syscall_arg3(ctx) & 0x100) { flag |= 0x1000; }; +#endif + #ifdef USE_NOCACHE_MMAP if ((ihk_mc_syscall_arg3(ctx) & 0x40) == 0x40) { @@ -290,11 +304,15 @@ SYSCALL_DECLARE(mmap) extend_process_region(cpu_local_var(current), region->map_start, map_end_aligned, - s + len, 0); + s + len, flag); } + if(ihk_mc_syscall_arg1(ctx) == 1024*1024*64 || ihk_mc_syscall_arg1(ctx) == 1024*1024*128) { + kprintf("syscall.c,mmap,cpuid=%d,map_end-len=%lx,s+len=%lx,map_end=%lx\n", ihk_mc_get_processor_id(), region->map_end-len, s+len, region->map_end); + } + ihk_mc_spinlock_unlock_noirq(&cpu_local_var(current)->vm->memory_range_lock); - dkprintf("syscall.c,mmap,map_end=%lx,s+len=%lx\n", region->map_end, s+len); + #ifdef USE_LARGE_PAGES if (region->map_end >= s + len) { /* NOTE: extend_process_region() might have large page aligned */