/proc/<PID>/mem: support read/write

This commit is contained in:
Tomoki Shirasawa
2016-02-16 13:21:29 +09:00
parent da13bd408a
commit 8c40f94aa8

View File

@@ -94,7 +94,6 @@ process_procfs_request(unsigned long rarg)
int npages; int npages;
int readwrite = 0; int readwrite = 0;
dprintf("process_procfs_request: invoked.\n"); dprintf("process_procfs_request: invoked.\n");
syscall_channel = get_cpu_local_var(0)->syscall_channel; syscall_channel = get_cpu_local_var(0)->syscall_channel;
@@ -162,33 +161,42 @@ process_procfs_request(unsigned long rarg)
*/ */
ret = sscanf(p, "%d/", &pid); ret = sscanf(p, "%d/", &pid);
if (ret == 1) { if (ret == 1) {
struct mcs_rwlock_node tlock;
int tids;
struct thread *thread1 = NULL;
proc = find_process(pid, &lock); proc = find_process(pid, &lock);
if(proc == NULL){ if(proc == NULL){
kprintf("process_procfs_request: no such pid %d\n", pid); kprintf("process_procfs_request: no such pid %d\n", pid);
goto end; goto end;
} }
p = strchr(p, '/') + 1; p = strchr(p, '/') + 1;
ret = sscanf(p, "task/%d/", &tid); if((tids = sscanf(p, "task/%d/", &tid)) == 1){
if(ret == 1){
struct mcs_rwlock_node tlock;
mcs_rwlock_reader_lock_noirq(&proc->threads_lock, &tlock);
list_for_each_entry(thread, &proc->threads_list,
siblings_list) {
if(thread->tid == tid)
break;
}
if(thread == NULL){
mcs_rwlock_reader_unlock_noirq(&proc->threads_lock,
&tlock);
process_unlock(proc, &lock);
kprintf("process_procfs_request: no such tid %d-%d\n", pid, tid);
goto end;
}
hold_thread(thread);
mcs_rwlock_reader_unlock_noirq(&proc->threads_lock, &tlock);
p = strchr(p, '/') + 1; p = strchr(p, '/') + 1;
p = strchr(p, '/') + 1; p = strchr(p, '/') + 1;
} }
else
tid = pid;
mcs_rwlock_reader_lock_noirq(&proc->threads_lock, &tlock);
list_for_each_entry(thread, &proc->threads_list, siblings_list){
if(thread->tid == tid)
break;
if(!thread1)
thread1 = thread;
}
if(thread == NULL){
kprintf("process_procfs_request: no such tid %d-%d\n", pid, tid);
if(tids){
process_unlock(proc, &lock);
mcs_rwlock_reader_unlock_noirq(&proc->threads_lock, &tlock);
goto end;
}
thread = thread1;
}
if(thread)
hold_thread(thread);
mcs_rwlock_reader_unlock_noirq(&proc->threads_lock, &tlock);
hold_process(proc); hold_process(proc);
vm = proc->vm; vm = proc->vm;
if(vm) if(vm)
@@ -235,73 +243,52 @@ process_procfs_request(unsigned long rarg)
* of the process. The count is the length of the area. * of the process. The count is the length of the area.
*/ */
if (strcmp(p, "mem") == 0) { if (strcmp(p, "mem") == 0) {
struct vm_range *range; uint64_t reason = PF_POPULATE | PF_WRITE | PF_USER;
unsigned long offset = r->offset;
unsigned long left = r->count;
int ret;
struct page_table *pt = vm->address_space->page_table;
if (proc != cpu_local_var(current)->proc) { ans = 0;
uint64_t reason = PF_POPULATE | PF_WRITE | PF_USER; if(left == 0)
unsigned long offset = r->offset; goto end;
unsigned long left = r->count;
int ret;
ans = 0; #if 0
if(left == 0) if(!(proc->ptrace & PT_TRACED) ||
goto end; !(proc->status & (PS_STOPPED | PS_TRACED))){
ans = -EIO;
while(left){ goto end;
unsigned long pa;
char *va;
int pos = offset & (PAGE_SIZE - 1);
int size = PAGE_SIZE - pos;
if(size > left)
size = left;
ret = page_fault_process_vm(vm, (void *)offset,
reason);
if(ret){
if(ans == 0)
ans = -EIO;
goto end;
}
ret = ihk_mc_pt_virt_to_phys(vm->address_space->page_table,
(void *)offset, &pa);
if(ret){
if(ans == 0)
ans = -EIO;
goto end;
}
va = phys_to_virt(pa);
memcpy(buf + ans, va, size);
offset += size;
left -= size;
ans += size;
}
} }
else{ #endif
unsigned long offset = r->offset;
unsigned long left = r->count; while(left){
unsigned long pos; unsigned long pa;
unsigned long l; char *va;
ans = 0; int pos = offset & (PAGE_SIZE - 1);
list_for_each_entry(range, &vm->vm_range_list, list) { int size = PAGE_SIZE - pos;
dprintf("range: %lx - %lx\n", range->start, range->end);
while (left && if(size > left)
(range->start <= offset) && size = left;
(offset < range->end)) { ret = page_fault_process_vm(vm, (void *)offset, reason);
pos = offset & (PAGE_SIZE - 1); if(ret){
l = PAGE_SIZE - pos; if(ans == 0)
if(l > left) ans = -EIO;
l = left; goto end;
if(copy_from_user(buf, (void *)offset, l)){
if(ans == 0)
ans = -EIO;
goto end;
}
buf += l;
ans += l;
offset += l;
left -= l;
}
} }
ret = ihk_mc_pt_virt_to_phys(pt, (void *)offset, &pa);
if(ret){
if(ans == 0)
ans = -EIO;
goto end;
}
va = phys_to_virt(pa);
if(readwrite)
memcpy(va, buf + ans, size);
else
memcpy(buf + ans, va, size);
offset += size;
left -= size;
ans += size;
} }
goto end; goto end;
} }