implementing demand paging to make it possible to run Intel OpenMP programs

This commit is contained in:
Masamichi Takagi m-takagi@ab.jp.nec.com
2013-07-02 21:31:38 +09:00
parent 75b51ec0c1
commit b59be07e9a
4 changed files with 79 additions and 10 deletions

View File

@ -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 <waitq.h>

View File

@ -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 */

View File

@ -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;
}

View File

@ -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 */