rus_vm_fault: always use a packet on the stack
There are valid use cases where a remote page fault has no available thread data/packet available to use, e.g. when device driver threads need to access the data (BXI). Do the per thread data lookup to use the right channel/tid if available, and use mcctrl_ikc_send_wait with a new message number directly. The fault is no longer handled in mckernel syscall forwarding code but in the ikc handler directly in irq, this should be ok because page faults are interrupts anyway so the code should be irq-safe. Change-Id: Ie60f413cdaee6c1a824b4a2c93637899cb9bf9c9
This commit is contained in:
committed by
Dominique Martinet
parent
8074445d59
commit
a5d5baf8a8
@@ -599,6 +599,7 @@ static int syscall_packet_handler(struct ihk_ikc_channel_desc *c,
|
||||
int ret = 0;
|
||||
struct perf_ctrl_desc *pcd;
|
||||
unsigned int mode = 0;
|
||||
unsigned long t_s = 0;
|
||||
|
||||
switch (packet->msg) {
|
||||
case SCD_MSG_INIT_CHANNEL_ACKED:
|
||||
@@ -660,6 +661,47 @@ static int syscall_packet_handler(struct ihk_ikc_channel_desc *c,
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case SCD_MSG_REMOTE_PAGE_FAULT:
|
||||
thread = find_thread(0, packet->fault_tid);
|
||||
if (!thread) {
|
||||
kprintf("%s: WARNING: no thread for remote pf %d\n",
|
||||
__func__, packet->fault_tid);
|
||||
pckt.err = ret = -EINVAL;
|
||||
goto out_remote_pf;
|
||||
}
|
||||
#ifdef PROFILE_ENABLE
|
||||
/* We cannot use thread->profile_start_ts here because the
|
||||
* caller may be utilizing it already */
|
||||
|
||||
if (thread->profile) {
|
||||
t_s = rdtsc();
|
||||
}
|
||||
#endif // PROFILE_ENABLE
|
||||
|
||||
dkprintf("remote page fault,pid=%d,va=%lx,reason=%x\n",
|
||||
thread->proc->pid, packet->fault_address,
|
||||
packet->fault_reason|PF_POPULATE);
|
||||
pckt.err = page_fault_process_vm(thread->vm,
|
||||
(void *)packet->fault_address,
|
||||
packet->fault_reason|PF_POPULATE);
|
||||
|
||||
#ifdef PROFILE_ENABLE
|
||||
if (thread->profile) {
|
||||
profile_event_add(PROFILE_remote_page_fault,
|
||||
(rdtsc() - t_s));
|
||||
}
|
||||
#endif // PROFILE_ENABLE
|
||||
thread_unlock(thread);
|
||||
|
||||
out_remote_pf:
|
||||
pckt.msg = SCD_MSG_REMOTE_PAGE_FAULT_ANSWER;
|
||||
pckt.ref = packet->ref;
|
||||
pckt.arg = packet->arg;
|
||||
pckt.reply = packet->reply;
|
||||
pckt.pid = packet->pid;
|
||||
syscall_channel_send(resp_channel, &pckt);
|
||||
break;
|
||||
|
||||
case SCD_MSG_SEND_SIGNAL:
|
||||
pp = ihk_mc_map_memory(NULL, packet->arg, sizeof(struct mcctrl_signal));
|
||||
sp = (struct mcctrl_signal *)ihk_mc_map_virtual(pp, 1, PTATTR_WRITABLE | PTATTR_ACTIVE);
|
||||
|
||||
@@ -52,6 +52,9 @@
|
||||
#define SCD_MSG_PROCFS_ANSWER 0x13
|
||||
#define SCD_MSG_PROCFS_RELEASE 0x15
|
||||
|
||||
#define SCD_MSG_REMOTE_PAGE_FAULT 0x18
|
||||
#define SCD_MSG_REMOTE_PAGE_FAULT_ANSWER 0x19
|
||||
|
||||
#define SCD_MSG_DEBUG_LOG 0x20
|
||||
|
||||
#define SCD_MSG_SYSFS_REQ_CREATE 0x30
|
||||
@@ -295,6 +298,14 @@ struct ikc_scd_packet {
|
||||
void *resp;
|
||||
int *spin_sleep; /* 1: waiting in linux_wait_event() 0: woken up by someone else */
|
||||
} futex;
|
||||
|
||||
/* SCD_MSG_REMOTE_PAGE_FAULT */
|
||||
struct {
|
||||
int target_cpu;
|
||||
int fault_tid;
|
||||
unsigned long fault_address;
|
||||
unsigned long fault_reason;
|
||||
};
|
||||
};
|
||||
/* char padding[8]; */ /* We want the size to be 128 bytes */
|
||||
};
|
||||
@@ -312,7 +323,6 @@ struct syscall_response {
|
||||
unsigned long req_thread_status;
|
||||
long ret;
|
||||
unsigned long fault_address;
|
||||
unsigned long fault_reason;
|
||||
};
|
||||
|
||||
struct syscall_post {
|
||||
|
||||
@@ -241,7 +241,7 @@ long do_syscall(struct syscall_request *req, int cpu)
|
||||
#define STATUS_IN_PROGRESS 0
|
||||
#define STATUS_COMPLETED 1
|
||||
#define STATUS_PAGE_FAULT 3
|
||||
#define STATUS_SYACALL 4
|
||||
#define STATUS_SYSCALL 4
|
||||
while (res.status != STATUS_COMPLETED) {
|
||||
while (res.status == STATUS_IN_PROGRESS) {
|
||||
struct cpu_local_var *v;
|
||||
@@ -295,42 +295,7 @@ long do_syscall(struct syscall_request *req, int cpu)
|
||||
cpu_restore_interrupt(flags);
|
||||
}
|
||||
|
||||
if (res.status == STATUS_PAGE_FAULT) {
|
||||
#ifdef PROFILE_ENABLE
|
||||
/* We cannot use thread->profile_start_ts here because the
|
||||
* caller may be utilizing it already */
|
||||
unsigned long t_s = 0;
|
||||
if (thread->profile) {
|
||||
t_s = rdtsc();
|
||||
}
|
||||
#endif // PROFILE_ENABLE
|
||||
|
||||
dkprintf("STATUS_PAGE_FAULT in syscall, pid: %d\n",
|
||||
cpu_local_var(current)->proc->pid);
|
||||
dkprintf("remote page fault,va=%lx,reason=%x\n", res.fault_address, res.fault_reason|PF_POPULATE);
|
||||
error = page_fault_process_vm(thread->vm,
|
||||
(void *)res.fault_address,
|
||||
res.fault_reason|PF_POPULATE);
|
||||
|
||||
/* send result */
|
||||
req2.number = __NR_mmap;
|
||||
#define PAGER_RESUME_PAGE_FAULT 0x0101
|
||||
req2.args[0] = PAGER_RESUME_PAGE_FAULT;
|
||||
req2.args[1] = error;
|
||||
/* The current thread is the requester and only the waiting thread
|
||||
* may serve the request */
|
||||
req2.rtid = cpu_local_var(current)->tid;
|
||||
req2.ttid = res.stid;
|
||||
|
||||
res.req_thread_status = IHK_SCD_REQ_THREAD_SPINNING;
|
||||
send_syscall(&req2, cpu, &res);
|
||||
#ifdef PROFILE_ENABLE
|
||||
profile_event_add(PROFILE_remote_page_fault,
|
||||
(rdtsc() - t_s));
|
||||
#endif // PROFILE_ENABLE
|
||||
}
|
||||
|
||||
if (res.status == STATUS_SYACALL) {
|
||||
if (res.status == STATUS_SYSCALL) {
|
||||
struct syscall_request *requestp;
|
||||
struct syscall_request request;
|
||||
int num;
|
||||
|
||||
Reference in New Issue
Block a user