add remove_process_memory_range()
This commit is contained in:
@@ -98,6 +98,8 @@ void free_process_memory(struct process *proc);
|
|||||||
int add_process_memory_range(struct process *process,
|
int add_process_memory_range(struct process *process,
|
||||||
unsigned long start, unsigned long end,
|
unsigned long start, unsigned long end,
|
||||||
unsigned long phys, unsigned long flag);
|
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,
|
int remove_process_region(struct process *proc,
|
||||||
unsigned long start, unsigned long end);
|
unsigned long start, unsigned long end);
|
||||||
struct program_load_desc;
|
struct program_load_desc;
|
||||||
|
|||||||
@@ -171,6 +171,96 @@ err:
|
|||||||
return -ENOMEM;
|
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,
|
int add_process_memory_range(struct process *process,
|
||||||
unsigned long start, unsigned long end,
|
unsigned long start, unsigned long end,
|
||||||
unsigned long phys, unsigned long flag)
|
unsigned long phys, unsigned long flag)
|
||||||
|
|||||||
@@ -506,12 +506,16 @@ SYSCALL_DECLARE(mmap)
|
|||||||
SYSCALL_DECLARE(munmap)
|
SYSCALL_DECLARE(munmap)
|
||||||
{
|
{
|
||||||
unsigned long address, len;
|
unsigned long address, len;
|
||||||
|
int error;
|
||||||
|
|
||||||
address = ihk_mc_syscall_arg0(ctx);
|
address = ihk_mc_syscall_arg0(ctx);
|
||||||
len = ihk_mc_syscall_arg1(ctx);
|
len = ihk_mc_syscall_arg1(ctx);
|
||||||
|
|
||||||
return remove_process_region(cpu_local_var(current), address,
|
ihk_mc_spinlock_lock_noirq(&cpu_local_var(current)->vm->memory_range_lock);
|
||||||
address + len);
|
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)
|
SYSCALL_DECLARE(mprotect)
|
||||||
|
|||||||
Reference in New Issue
Block a user