Kernel: delivermsg improvements
. make arch-independent, and local to proc.c, reduce code duplication . make vm_suspend public but unduplicated in proc.c . ask VM for handling once, 2nd time SIGSEGV process . remove debug printfs . test case for bogus sendrec() address argument Change-Id: I3893758910c01de60b8fe3e50edd594296a0b73e
This commit is contained in:
parent
36f477c20e
commit
8bab0dfa2a
5 changed files with 69 additions and 120 deletions
|
@ -394,35 +394,6 @@ size_t vm_lookup_range(const struct proc *proc, vir_bytes vir_addr,
|
|||
return MIN(bytes, len);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* vm_suspend *
|
||||
*===========================================================================*/
|
||||
static void vm_suspend(struct proc *caller, const struct proc *target,
|
||||
const vir_bytes linaddr, const vir_bytes len, const int type,
|
||||
const int writeflag)
|
||||
{
|
||||
/* This range is not OK for this process. Set parameters
|
||||
* of the request and notify VM about the pending request.
|
||||
*/
|
||||
assert(!RTS_ISSET(caller, RTS_VMREQUEST));
|
||||
assert(!RTS_ISSET(target, RTS_VMREQUEST));
|
||||
|
||||
RTS_SET(caller, RTS_VMREQUEST);
|
||||
|
||||
caller->p_vmrequest.req_type = VMPTYPE_CHECK;
|
||||
caller->p_vmrequest.target = target->p_endpoint;
|
||||
caller->p_vmrequest.params.check.start = linaddr;
|
||||
caller->p_vmrequest.params.check.length = len;
|
||||
caller->p_vmrequest.params.check.writeflag = writeflag;
|
||||
caller->p_vmrequest.type = type;
|
||||
|
||||
/* Connect caller on vmrequest wait queue. */
|
||||
if(!(caller->p_vmrequest.nextrequestor = vmrequest))
|
||||
if(OK != send_sig(VM_PROC_NR, SIGKMEM))
|
||||
panic("send_sig failed");
|
||||
vmrequest = caller;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* vm_check_range *
|
||||
*===========================================================================*/
|
||||
|
@ -449,35 +420,6 @@ int vm_check_range(struct proc *caller, struct proc *target,
|
|||
return VMSUSPEND;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* delivermsg *
|
||||
*===========================================================================*/
|
||||
void delivermsg(struct proc *rp)
|
||||
{
|
||||
int r = OK;
|
||||
|
||||
assert(rp->p_misc_flags & MF_DELIVERMSG);
|
||||
assert(rp->p_delivermsg.m_source != NONE);
|
||||
|
||||
if (copy_msg_to_user(&rp->p_delivermsg,
|
||||
(message *) rp->p_delivermsg_vir)) {
|
||||
printf("WARNING wrong user pointer 0x%08lx from "
|
||||
"process %s / %d\n",
|
||||
rp->p_delivermsg_vir,
|
||||
rp->p_name,
|
||||
rp->p_endpoint);
|
||||
r = EFAULT;
|
||||
}
|
||||
|
||||
/* Indicate message has been delivered; address is 'used'. */
|
||||
rp->p_delivermsg.m_source = NONE;
|
||||
rp->p_misc_flags &= ~MF_DELIVERMSG;
|
||||
|
||||
if(!(rp->p_misc_flags & MF_CONTEXT_SET)) {
|
||||
rp->p_reg.retreg = r;
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* vmmemset *
|
||||
*===========================================================================*/
|
||||
|
|
|
@ -421,37 +421,6 @@ size_t vm_lookup_range(const struct proc *proc, vir_bytes vir_addr,
|
|||
return MIN(bytes, len);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* vm_suspend *
|
||||
*===========================================================================*/
|
||||
static void vm_suspend(struct proc *caller, const struct proc *target,
|
||||
const vir_bytes linaddr, const vir_bytes len, const int type,
|
||||
const int writeflag)
|
||||
{
|
||||
/* This range is not OK for this process. Set parameters
|
||||
* of the request and notify VM about the pending request.
|
||||
*/
|
||||
assert(!RTS_ISSET(caller, RTS_VMREQUEST));
|
||||
assert(!RTS_ISSET(target, RTS_VMREQUEST));
|
||||
|
||||
RTS_SET(caller, RTS_VMREQUEST);
|
||||
|
||||
assert(caller->p_endpoint != VM_PROC_NR);
|
||||
|
||||
caller->p_vmrequest.req_type = VMPTYPE_CHECK;
|
||||
caller->p_vmrequest.target = target->p_endpoint;
|
||||
caller->p_vmrequest.params.check.start = linaddr;
|
||||
caller->p_vmrequest.params.check.length = len;
|
||||
caller->p_vmrequest.params.check.writeflag = writeflag;
|
||||
caller->p_vmrequest.type = type;
|
||||
|
||||
/* Connect caller on vmrequest wait queue. */
|
||||
if(!(caller->p_vmrequest.nextrequestor = vmrequest))
|
||||
if(OK != send_sig(VM_PROC_NR, SIGKMEM))
|
||||
panic("send_sig failed");
|
||||
vmrequest = caller;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* vm_check_range *
|
||||
*===========================================================================*/
|
||||
|
@ -478,36 +447,6 @@ int vm_check_range(struct proc *caller, struct proc *target,
|
|||
return VMSUSPEND;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* delivermsg *
|
||||
*===========================================================================*/
|
||||
void delivermsg(struct proc *rp)
|
||||
{
|
||||
int r = OK;
|
||||
|
||||
assert(rp->p_misc_flags & MF_DELIVERMSG);
|
||||
assert(rp->p_delivermsg.m_source != NONE);
|
||||
|
||||
if (copy_msg_to_user(&rp->p_delivermsg,
|
||||
(message *) rp->p_delivermsg_vir)) {
|
||||
printf("WARNING wrong user pointer 0x%08lx from "
|
||||
"process %s / %d\n",
|
||||
rp->p_delivermsg_vir,
|
||||
rp->p_name,
|
||||
rp->p_endpoint);
|
||||
cause_sig(rp->p_nr, SIGSEGV);
|
||||
r = EFAULT;
|
||||
}
|
||||
|
||||
/* Indicate message has been delivered; address is 'used'. */
|
||||
rp->p_delivermsg.m_source = NONE;
|
||||
rp->p_misc_flags &= ~MF_DELIVERMSG;
|
||||
|
||||
if(!(rp->p_misc_flags & MF_CONTEXT_SET)) {
|
||||
rp->p_reg.retreg = r;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static char *flagstr(u32_t e, const int dir)
|
||||
{
|
||||
|
|
|
@ -231,6 +231,71 @@ static void idle(void)
|
|||
*/
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* vm_suspend *
|
||||
*===========================================================================*/
|
||||
void vm_suspend(struct proc *caller, const struct proc *target,
|
||||
const vir_bytes linaddr, const vir_bytes len, const int type,
|
||||
const int writeflag)
|
||||
{
|
||||
/* This range is not OK for this process. Set parameters
|
||||
* of the request and notify VM about the pending request.
|
||||
*/
|
||||
assert(!RTS_ISSET(caller, RTS_VMREQUEST));
|
||||
assert(!RTS_ISSET(target, RTS_VMREQUEST));
|
||||
|
||||
RTS_SET(caller, RTS_VMREQUEST);
|
||||
|
||||
caller->p_vmrequest.req_type = VMPTYPE_CHECK;
|
||||
caller->p_vmrequest.target = target->p_endpoint;
|
||||
caller->p_vmrequest.params.check.start = linaddr;
|
||||
caller->p_vmrequest.params.check.length = len;
|
||||
caller->p_vmrequest.params.check.writeflag = writeflag;
|
||||
caller->p_vmrequest.type = type;
|
||||
|
||||
/* Connect caller on vmrequest wait queue. */
|
||||
if(!(caller->p_vmrequest.nextrequestor = vmrequest))
|
||||
if(OK != send_sig(VM_PROC_NR, SIGKMEM))
|
||||
panic("send_sig failed");
|
||||
vmrequest = caller;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* delivermsg *
|
||||
*===========================================================================*/
|
||||
static void delivermsg(struct proc *rp)
|
||||
{
|
||||
assert(!RTS_ISSET(rp, RTS_VMREQUEST));
|
||||
assert(rp->p_misc_flags & MF_DELIVERMSG);
|
||||
assert(rp->p_delivermsg.m_source != NONE);
|
||||
|
||||
if (copy_msg_to_user(&rp->p_delivermsg,
|
||||
(message *) rp->p_delivermsg_vir)) {
|
||||
if(rp->p_misc_flags & MF_MSGFAILED) {
|
||||
/* 2nd consecutive failure means this won't succeed */
|
||||
printf("WARNING wrong user pointer 0x%08lx from "
|
||||
"process %s / %d\n",
|
||||
rp->p_delivermsg_vir,
|
||||
rp->p_name,
|
||||
rp->p_endpoint);
|
||||
cause_sig(rp->p_nr, SIGSEGV);
|
||||
} else {
|
||||
/* 1st failure means we have to ask VM to handle it */
|
||||
vm_suspend(rp, rp, rp->p_delivermsg_vir,
|
||||
sizeof(message), VMSTYPE_DELIVERMSG, 1);
|
||||
rp->p_misc_flags |= MF_MSGFAILED;
|
||||
}
|
||||
} else {
|
||||
/* Indicate message has been delivered; address is 'used'. */
|
||||
rp->p_delivermsg.m_source = NONE;
|
||||
rp->p_misc_flags &= ~(MF_DELIVERMSG|MF_MSGFAILED);
|
||||
|
||||
if(!(rp->p_misc_flags & MF_CONTEXT_SET)) {
|
||||
rp->p_reg.retreg = OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* switch_to_user *
|
||||
*===========================================================================*/
|
||||
|
|
|
@ -255,6 +255,7 @@ struct proc {
|
|||
because of VM modifying the sender's address
|
||||
space*/
|
||||
#define MF_STEP 0x40000 /* Single-step process */
|
||||
#define MF_MSGFAILED 0x80000
|
||||
|
||||
/* Magic process table addresses. */
|
||||
#define BEG_PROC_ADDR (&proc[0])
|
||||
|
|
|
@ -59,6 +59,9 @@ int has_pending_notify(struct proc * caller, int src_p);
|
|||
int has_pending_asend(struct proc * caller, int src_p);
|
||||
void unset_notify_pending(struct proc * caller, int src_p);
|
||||
int mini_notify(const struct proc *src, endpoint_t dst);
|
||||
void vm_suspend(struct proc *caller, const struct proc *target,
|
||||
const vir_bytes linaddr, const vir_bytes len, const int type,
|
||||
const int writeflag);
|
||||
void enqueue(struct proc *rp);
|
||||
void dequeue(struct proc *rp);
|
||||
void switch_to_user(void);
|
||||
|
@ -215,7 +218,6 @@ int vm_lookup(const struct proc *proc, vir_bytes virtual, phys_bytes
|
|||
*result, u32_t *ptent);
|
||||
size_t vm_lookup_range(const struct proc *proc,
|
||||
vir_bytes vir_addr, phys_bytes *phys_addr, size_t bytes);
|
||||
void delivermsg(struct proc *target);
|
||||
void arch_do_syscall(struct proc *proc);
|
||||
int arch_phys_map(int index, phys_bytes *addr, phys_bytes *len, int
|
||||
*flags);
|
||||
|
|
Loading…
Reference in a new issue