implementing demand paging to make it possible to run Intel OpenMP programs
This commit is contained in:
parent
75b51ec0c1
commit
b59be07e9a
@ -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>
|
||||
|
||||
31
kernel/mem.c
31
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 */
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user