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 *
*===========================================================================*/
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 *
*===========================================================================*/
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 *
*===========================================================================*/
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)
{
*/
}
+/*===========================================================================*
+ * 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 *
*===========================================================================*/
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])
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);
*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);