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);
|
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 *
|
* vm_check_range *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -449,35 +420,6 @@ int vm_check_range(struct proc *caller, struct proc *target,
|
||||||
return VMSUSPEND;
|
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 *
|
* vmmemset *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
|
|
@ -421,37 +421,6 @@ size_t vm_lookup_range(const struct proc *proc, vir_bytes vir_addr,
|
||||||
return MIN(bytes, len);
|
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 *
|
* vm_check_range *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -478,36 +447,6 @@ int vm_check_range(struct proc *caller, struct proc *target,
|
||||||
return VMSUSPEND;
|
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
|
#if 0
|
||||||
static char *flagstr(u32_t e, const int dir)
|
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 *
|
* switch_to_user *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
|
|
@ -255,6 +255,7 @@ struct proc {
|
||||||
because of VM modifying the sender's address
|
because of VM modifying the sender's address
|
||||||
space*/
|
space*/
|
||||||
#define MF_STEP 0x40000 /* Single-step process */
|
#define MF_STEP 0x40000 /* Single-step process */
|
||||||
|
#define MF_MSGFAILED 0x80000
|
||||||
|
|
||||||
/* Magic process table addresses. */
|
/* Magic process table addresses. */
|
||||||
#define BEG_PROC_ADDR (&proc[0])
|
#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);
|
int has_pending_asend(struct proc * caller, int src_p);
|
||||||
void unset_notify_pending(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);
|
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 enqueue(struct proc *rp);
|
||||||
void dequeue(struct proc *rp);
|
void dequeue(struct proc *rp);
|
||||||
void switch_to_user(void);
|
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);
|
*result, u32_t *ptent);
|
||||||
size_t vm_lookup_range(const struct proc *proc,
|
size_t vm_lookup_range(const struct proc *proc,
|
||||||
vir_bytes vir_addr, phys_bytes *phys_addr, size_t bytes);
|
vir_bytes vir_addr, phys_bytes *phys_addr, size_t bytes);
|
||||||
void delivermsg(struct proc *target);
|
|
||||||
void arch_do_syscall(struct proc *proc);
|
void arch_do_syscall(struct proc *proc);
|
||||||
int arch_phys_map(int index, phys_bytes *addr, phys_bytes *len, int
|
int arch_phys_map(int index, phys_bytes *addr, phys_bytes *len, int
|
||||||
*flags);
|
*flags);
|
||||||
|
|
Loading…
Reference in a new issue