mirror of
https://github.com/drasko/codezero.git
synced 2026-03-03 11:03:16 +01:00
Added ipc save/restore for page-fault ipcs.
The save restore routines save all primary message registers and ipc flags.
This commit is contained in:
@@ -145,15 +145,29 @@ static inline unsigned int tcb_get_ipc_flags(struct ktcb *task)
|
|||||||
return task->ipc_flags;
|
return task->ipc_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline unsigned int
|
||||||
|
ipc_flags_set_type(unsigned int flags, unsigned int type)
|
||||||
|
{
|
||||||
|
flags &= ~IPC_FLAGS_TYPE_MASK;
|
||||||
|
flags |= type & IPC_FLAGS_TYPE_MASK;
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int ipc_flags_get_type(unsigned int flags)
|
||||||
|
{
|
||||||
|
return flags & IPC_FLAGS_TYPE_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void tcb_set_ipc_type(struct ktcb *task,
|
static inline void tcb_set_ipc_type(struct ktcb *task,
|
||||||
unsigned int type)
|
unsigned int type)
|
||||||
{
|
{
|
||||||
task->ipc_flags = type & IPC_FLAGS_TYPE_MASK;
|
task->ipc_flags = ipc_flags_set_type(task->ipc_flags,
|
||||||
|
type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned int tcb_get_ipc_type(struct ktcb *task)
|
static inline unsigned int tcb_get_ipc_type(struct ktcb *task)
|
||||||
{
|
{
|
||||||
return task->ipc_flags & IPC_FLAGS_TYPE_MASK;
|
return ipc_flags_get_type(task->ipc_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define THREAD_IDS_MAX 1024
|
#define THREAD_IDS_MAX 1024
|
||||||
|
|||||||
@@ -506,29 +506,38 @@ static inline int __sys_ipc(l4id_t to, l4id_t from,
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
switch (ipc_type) {
|
if (ipc_flags_get_type(flags) == IPC_FLAGS_EXTENDED) {
|
||||||
case IPC_SEND:
|
switch (ipc_type) {
|
||||||
if (flags & IPC_FLAGS_EXTENDED)
|
case IPC_SEND:
|
||||||
ret = ipc_send_extended(to, flags);
|
ret = ipc_send_extended(to, flags);
|
||||||
else
|
break;
|
||||||
ret = ipc_send(to, flags);
|
case IPC_RECV:
|
||||||
break;
|
|
||||||
case IPC_RECV:
|
|
||||||
if (flags & IPC_FLAGS_EXTENDED)
|
|
||||||
ret = ipc_recv_extended(from, flags);
|
ret = ipc_recv_extended(from, flags);
|
||||||
else
|
break;
|
||||||
ret = ipc_recv(from, flags);
|
case IPC_SENDRECV:
|
||||||
break;
|
|
||||||
case IPC_SENDRECV:
|
|
||||||
if (flags & IPC_FLAGS_EXTENDED)
|
|
||||||
ret = ipc_sendrecv_extended(to, from, flags);
|
ret = ipc_sendrecv_extended(to, from, flags);
|
||||||
else
|
break;
|
||||||
|
case IPC_INVALID:
|
||||||
|
default:
|
||||||
|
printk("Unsupported ipc operation.\n");
|
||||||
|
ret = -ENOSYS;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (ipc_type) {
|
||||||
|
case IPC_SEND:
|
||||||
|
ret = ipc_send(to, flags);
|
||||||
|
break;
|
||||||
|
case IPC_RECV:
|
||||||
|
ret = ipc_recv(from, flags);
|
||||||
|
break;
|
||||||
|
case IPC_SENDRECV:
|
||||||
ret = ipc_sendrecv(to, from, flags);
|
ret = ipc_sendrecv(to, from, flags);
|
||||||
break;
|
break;
|
||||||
case IPC_INVALID:
|
case IPC_INVALID:
|
||||||
default:
|
default:
|
||||||
printk("Unsupported ipc operation.\n");
|
printk("Unsupported ipc operation.\n");
|
||||||
ret = -ENOSYS;
|
ret = -ENOSYS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,39 @@
|
|||||||
#define dbg_abort(...)
|
#define dbg_abort(...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct ipc_state {
|
||||||
|
u32 mr[MR_TOTAL];
|
||||||
|
unsigned int flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
void ipc_save_state(struct ipc_state *state)
|
||||||
|
{
|
||||||
|
unsigned int *mr0_current = KTCB_REF_MR0(current);
|
||||||
|
|
||||||
|
BUG_ON(!mr0_current);
|
||||||
|
|
||||||
|
/* Save primary message registers */
|
||||||
|
for (int i = 0; i < MR_TOTAL; i++)
|
||||||
|
state->mr[i] = mr0_current[i];
|
||||||
|
|
||||||
|
/* Save ipc flags */
|
||||||
|
state->flags = tcb_get_ipc_flags(current);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ipc_restore_state(struct ipc_state *state)
|
||||||
|
{
|
||||||
|
unsigned int *mr0_current = KTCB_REF_MR0(current);
|
||||||
|
|
||||||
|
BUG_ON(!mr0_current);
|
||||||
|
|
||||||
|
/* Restore primary message registers */
|
||||||
|
for (int i = 0; i < MR_TOTAL; i++)
|
||||||
|
mr0_current[i] = state->mr[i];
|
||||||
|
|
||||||
|
/* Restore ipc flags */
|
||||||
|
tcb_set_ipc_flags(current, state->flags);
|
||||||
|
}
|
||||||
|
|
||||||
/* Send data fault ipc to the faulty task's pager */
|
/* Send data fault ipc to the faulty task's pager */
|
||||||
void fault_ipc_to_pager(u32 faulty_pc, u32 fsr, u32 far)
|
void fault_ipc_to_pager(u32 faulty_pc, u32 fsr, u32 far)
|
||||||
{
|
{
|
||||||
@@ -32,7 +65,6 @@ void fault_ipc_to_pager(u32 faulty_pc, u32 fsr, u32 far)
|
|||||||
u32 mr[MR_TOTAL] = { [MR_TAG] = L4_IPC_TAG_PFAULT,
|
u32 mr[MR_TOTAL] = { [MR_TAG] = L4_IPC_TAG_PFAULT,
|
||||||
[MR_SENDER] = current->tid };
|
[MR_SENDER] = current->tid };
|
||||||
fault_kdata_t *fault = (fault_kdata_t *)&mr[MR_UNUSED_START];
|
fault_kdata_t *fault = (fault_kdata_t *)&mr[MR_UNUSED_START];
|
||||||
unsigned int saved_flags;
|
|
||||||
|
|
||||||
/* Fill in fault information to pass over during ipc */
|
/* Fill in fault information to pass over during ipc */
|
||||||
fault->faulty_pc = faulty_pc;
|
fault->faulty_pc = faulty_pc;
|
||||||
@@ -58,16 +90,12 @@ void fault_ipc_to_pager(u32 faulty_pc, u32 fsr, u32 far)
|
|||||||
((unsigned long)&mr[0] -
|
((unsigned long)&mr[0] -
|
||||||
offsetof(syscall_context_t, r3));
|
offsetof(syscall_context_t, r3));
|
||||||
|
|
||||||
/* Save current ipc flags and set current flags to short ipc */
|
/* Set current flags to short ipc */
|
||||||
saved_flags = tcb_get_ipc_flags(current);
|
|
||||||
tcb_set_ipc_flags(current, IPC_FLAGS_SHORT);
|
tcb_set_ipc_flags(current, IPC_FLAGS_SHORT);
|
||||||
|
|
||||||
/* Send ipc to the task's pager */
|
/* Send ipc to the task's pager */
|
||||||
ipc_sendrecv(current->pagerid, current->pagerid, 0);
|
ipc_sendrecv(current->pagerid, current->pagerid, 0);
|
||||||
|
|
||||||
/* Restore ipc flags */
|
|
||||||
tcb_set_ipc_flags(current, saved_flags);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FIXME: CHECK TASK KILL REPLY !!!
|
* FIXME: CHECK TASK KILL REPLY !!!
|
||||||
* Here, pager has handled the request and sent us back a message.
|
* Here, pager has handled the request and sent us back a message.
|
||||||
@@ -87,15 +115,22 @@ int pager_pagein_request(unsigned long addr, unsigned long size, unsigned int fl
|
|||||||
{
|
{
|
||||||
u32 abort;
|
u32 abort;
|
||||||
unsigned long npages = __pfn(align_up(size, PAGE_SIZE));
|
unsigned long npages = __pfn(align_up(size, PAGE_SIZE));
|
||||||
|
struct ipc_state ipc_state;
|
||||||
|
|
||||||
set_abort_type(abort, ARM_DABT);
|
set_abort_type(abort, ARM_DABT);
|
||||||
|
|
||||||
printk("%s: Kernel initiating paging-in requests\n", __FUNCTION__);
|
// printk("%s: Kernel initiating paging-in requests\n", __FUNCTION__);
|
||||||
|
|
||||||
|
/* Save current ipc state */
|
||||||
|
ipc_save_state(&ipc_state);
|
||||||
|
|
||||||
/* For every page to be used by the kernel send a page-in request */
|
/* For every page to be used by the kernel send a page-in request */
|
||||||
for (int i = 0; i < npages; i++)
|
for (int i = 0; i < npages; i++)
|
||||||
fault_ipc_to_pager(0, abort, addr + (i * PAGE_SIZE));
|
fault_ipc_to_pager(0, abort, addr + (i * PAGE_SIZE));
|
||||||
|
|
||||||
|
/* Restore ipc state */
|
||||||
|
ipc_restore_state(&ipc_state);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user