add remove_process_memory_range()

This commit is contained in:
NAKAMURA Gou
2013-06-11 13:44:23 +09:00
parent 5206ae7d57
commit 8436f5a5ac
3 changed files with 98 additions and 2 deletions

View File

@@ -98,6 +98,8 @@ void free_process_memory(struct process *proc);
int add_process_memory_range(struct process *process,
unsigned long start, unsigned long end,
unsigned long phys, unsigned long flag);
int remove_process_memory_range(
struct process *process, unsigned long start, unsigned long end);
int remove_process_region(struct process *proc,
unsigned long start, unsigned long end);
struct program_load_desc;

View File

@@ -171,6 +171,96 @@ err:
return -ENOMEM;
}
int remove_process_memory_range(struct process *process, unsigned long start, unsigned long end)
{
struct process_vm * const vm = process->vm;
struct vm_range *range;
struct vm_range *next;
int error;
unsigned long freestart;
unsigned long freephys;
unsigned long freesize;
struct vm_range *freerange;
struct vm_range *newrange;
list_for_each_entry_safe(range, next, &vm->vm_range_list, list) {
if ((range->end <= start) || (end <= range->start)) {
/* no overlap */
continue;
}
error = 0;
freerange = NULL;
freesize = 0;
if (start <= range->start) {
/* partial or whole delete from range->start */
freestart = range->start;
freephys = range->phys;
freesize = end - range->start;
if (freesize >= (range->end - range->start)) {
freesize = range->end - range->start;
list_del(&range->list);
freerange = range;
}
else {
range->start += freesize;
range->phys += freesize;
}
}
else if (range->end <= end) {
/* partial delete up to range->end */
freestart = start;
freephys = range->phys + (start - range->start);
freesize = range->end - start;
range->end = start;
}
else {
/* delete the middle part of the 'range' */
freestart = start;
freephys = range->phys + (start - range->start);
freesize = end - start;
newrange = kmalloc(sizeof(struct vm_range), IHK_MC_AP_NOWAIT);
if (!newrange) {
kprintf("remove_process_memory_range:kmalloc failed\n");
return -ENOMEM;
}
INIT_LIST_HEAD(&range->list);
newrange->start = end;
newrange->end = range->end;
newrange->phys = range->phys + (end - range->start);
newrange->flag = range->flag;
list_add_tail(&newrange->list, &vm->vm_range_list);
range->end = start;
}
if (freesize > 0) {
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))) {
// XXX: need TLB shootdown?
ihk_mc_free_pages(phys_to_virt(freephys), freesize>>PAGE_SHIFT);
}
}
if (freerange != NULL) {
ihk_mc_free(freerange);
}
if (error) {
return error;
}
}
return 0;
}
int add_process_memory_range(struct process *process,
unsigned long start, unsigned long end,
unsigned long phys, unsigned long flag)

View File

@@ -506,12 +506,16 @@ SYSCALL_DECLARE(mmap)
SYSCALL_DECLARE(munmap)
{
unsigned long address, len;
int error;
address = ihk_mc_syscall_arg0(ctx);
len = ihk_mc_syscall_arg1(ctx);
return remove_process_region(cpu_local_var(current), address,
address + len);
ihk_mc_spinlock_lock_noirq(&cpu_local_var(current)->vm->memory_range_lock);
error = remove_process_memory_range(cpu_local_var(current), address, address+len);
ihk_mc_spinlock_unlock_noirq(&cpu_local_var(current)->vm->memory_range_lock);
return error;
}
SYSCALL_DECLARE(mprotect)