From 5d9efa72419179f8909d62e18665784282d3201c Mon Sep 17 00:00:00 2001 From: Tomoki Shirasawa Date: Sun, 2 Jun 2013 13:54:38 +0900 Subject: [PATCH] add rollback when ihk_mc_pt_set_page returns error --- arch/x86/kernel/memory.c | 5 +++++ kernel/process.c | 33 ++++++++++++++++++++++++++++----- lib/include/ihk/mm.h | 1 + 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/memory.c b/arch/x86/kernel/memory.c index fe6077fe..34d20626 100644 --- a/arch/x86/kernel/memory.c +++ b/arch/x86/kernel/memory.c @@ -621,6 +621,11 @@ int ihk_mc_pt_clear_page(page_table_t pt, void *virt) return __clear_pt_page(pt, virt, 0); } +int ihk_mc_pt_clear_large_page(page_table_t pt, void *virt) +{ + return __clear_pt_page(pt, virt, 1); +} + void load_page_table(struct page_table *pt) { unsigned long pt_addr; diff --git a/kernel/process.c b/kernel/process.c index 51cc4566..cdc8d1db 100644 --- a/kernel/process.c +++ b/kernel/process.c @@ -112,7 +112,7 @@ static int update_process_page_table(struct process *process, struct vm_range *range, enum ihk_mc_pt_attribute flag) { unsigned long p, pa = range->phys; - + unsigned long pp; unsigned long flags = ihk_mc_spinlock_lock(&process->vm->page_table_lock); p = range->start; while (p < range->end) { @@ -125,8 +125,7 @@ static int update_process_page_table(struct process *process, if (ihk_mc_pt_set_large_page(process->vm->page_table, (void *)p, pa, PTATTR_WRITABLE | PTATTR_USER | flag) != 0) { - kprintf("ERROR:setting large page for 0x%lX -> 0x%lX\n", p, pa); - panic(""); + goto err; } dkprintf("large page set for 0x%lX -> 0x%lX\n", p, pa); @@ -138,8 +137,7 @@ static int update_process_page_table(struct process *process, #endif if(ihk_mc_pt_set_page(process->vm->page_table, (void *)p, pa, PTATTR_WRITABLE | PTATTR_USER | flag) != 0){ - ihk_mc_spinlock_unlock(&process->vm->page_table_lock, flags); - return -ENOMEM; + goto err; } pa += PAGE_SIZE; @@ -150,6 +148,31 @@ static int update_process_page_table(struct process *process, } ihk_mc_spinlock_unlock(&process->vm->page_table_lock, flags); return 0; + +err: + pp = range->start; + pa = range->phys; + while(pp < p){ +#ifdef USE_LARGE_PAGES + if ((p & (LARGE_PAGE_SIZE - 1)) == 0 && + (pa & (LARGE_PAGE_SIZE - 1)) == 0 && + (range->end - p) >= LARGE_PAGE_SIZE) { + ihk_mc_pt_clear_large_page(process->vm->page_table, (void *)pp); + pa += LARGE_PAGE_SIZE; + pp += LARGE_PAGE_SIZE; + } + else{ +#endif + ihk_mc_pt_clear_page(process->vm->page_table, (void *)pp); + pa += PAGE_SIZE; + pp += PAGE_SIZE; +#ifdef USE_LARGE_PAGES + } +#endif + } + + ihk_mc_spinlock_unlock(&process->vm->page_table_lock, flags); + return -ENOMEM; } #if 0 diff --git a/lib/include/ihk/mm.h b/lib/include/ihk/mm.h index 7cdd5034..b619181c 100644 --- a/lib/include/ihk/mm.h +++ b/lib/include/ihk/mm.h @@ -91,6 +91,7 @@ int ihk_mc_pt_set_large_page(page_table_t pt, void *virt, int ihk_mc_pt_change_page(page_table_t pt, void *virt, enum ihk_mc_pt_attribute); int ihk_mc_pt_clear_page(page_table_t pt, void *virt); +int ihk_mc_pt_clear_large_page(page_table_t pt, void *virt); int ihk_mc_pt_prepare_map(page_table_t pt, void *virt, unsigned long size, enum ihk_mc_pt_prepare_flag);