static int __wind_errno_taskget(struct task_struct *curr, struct pt_regs *regs) { xnhandle_t handle = __xn_reg_arg1(regs); WIND_TCB *pTcb; int errcode; if (!__xn_access_ok (curr, VERIFY_WRITE, __xn_reg_arg2(regs), sizeof(errcode))) return -EFAULT; if (!handle) errcode = wind_errnoget(); else { pTcb = (WIND_TCB *)xnregistry_fetch(handle); if (!pTcb) return S_objLib_OBJ_ID_ERROR; errcode = errnoOfTaskGet((TASK_ID) pTcb); if (errcode == ERROR) return wind_errnoget(); } __xn_copy_to_user(curr, (void __user *)__xn_reg_arg2(regs), &errcode, sizeof(errcode)); return 0; }
static int __wind_task_priorityget(struct task_struct *curr, struct pt_regs *regs) { xnhandle_t handle = __xn_reg_arg1(regs); WIND_TCB *pTcb; int prio; if (!__xn_access_ok (curr, VERIFY_WRITE, __xn_reg_arg2(regs), sizeof(prio))) return -EFAULT; if (handle) pTcb = (WIND_TCB *)xnregistry_fetch(handle); else pTcb = __wind_task_current(curr); if (!pTcb) return S_objLib_OBJ_ID_ERROR; if (taskPriorityGet((TASK_ID) pTcb, &prio) == ERROR) return wind_errnoget(); __xn_copy_to_user(curr, (void __user *)__xn_reg_arg2(regs), &prio, sizeof(prio)); return 0; }
static int __wind_task_unsafe(struct task_struct *curr, struct pt_regs *regs) { if (taskUnsafe() == ERROR) return wind_errnoget(); return 0; }
static int __wind_task_nametoid(struct task_struct *curr, struct pt_regs *regs) { char name[XNOBJECT_NAME_LEN]; WIND_TCB_PLACEHOLDER ph; xnhandle_t handle; if (!__xn_access_ok (curr, VERIFY_WRITE, __xn_reg_arg2(regs), sizeof(ph))) return -EFAULT; if (!__xn_reg_arg1(regs)) return S_taskLib_NAME_NOT_FOUND; if (!__xn_access_ok (curr, VERIFY_READ, __xn_reg_arg1(regs), sizeof(name))) return -EFAULT; __xn_strncpy_from_user(curr, name, (const char __user *)__xn_reg_arg1(regs), sizeof(name) - 1); name[sizeof(name) - 1] = '\0'; handle = taskNameToHandle(name); if (handle == XN_NO_HANDLE) return wind_errnoget(); ph.handle = handle; /* Copy back the task handle. */ __xn_copy_to_user(curr, (void __user *)__xn_reg_arg2(regs), &ph, sizeof(ph)); return 0; }
static int __wind_msgq_nummsgs(struct task_struct *curr, struct pt_regs *regs) { xnhandle_t handle = __xn_reg_arg1(regs); wind_msgq_t *msgq; int nummsgs; if (!__xn_access_ok (curr, VERIFY_WRITE, __xn_reg_arg2(regs), sizeof(nummsgs))) return -EFAULT; msgq = (wind_msgq_t *)xnregistry_fetch(handle); if (!msgq) return S_objLib_OBJ_ID_ERROR; nummsgs = msgQNumMsgs((MSG_Q_ID)msgq); if (nummsgs == ERROR) return wind_errnoget(); __xn_copy_to_user(curr, (void __user *)__xn_reg_arg2(regs), &nummsgs, sizeof(nummsgs)); return 0; }
static int __wind_task_delay(struct task_struct *curr, struct pt_regs *regs) { int ticks = __xn_reg_arg1(regs); if (taskDelay(ticks) == ERROR) return wind_errnoget(); return 0; }
static int __wind_errno_taskget(struct pt_regs *regs) { xnhandle_t handle = __xn_reg_arg1(regs); WIND_TCB *pTcb; int errcode; if (!handle) errcode = wind_errnoget(); else { pTcb = __wind_lookup_task(handle); if (!pTcb) return S_objLib_OBJ_ID_ERROR; errcode = errnoOfTaskGet((TASK_ID) pTcb); if (errcode == ERROR) return wind_errnoget(); } return __xn_safe_copy_to_user((void __user *)__xn_reg_arg2(regs), &errcode, sizeof(errcode)); }
static int __wind_task_resume(struct pt_regs *regs) { WIND_TCB *pTcb = __wind_lookup_task(__xn_reg_arg1(regs)); if (!pTcb) return S_objLib_OBJ_ID_ERROR; if (taskResume((TASK_ID) pTcb) == ERROR) return wind_errnoget(); return 0; }
static int __wind_task_resume(struct task_struct *curr, struct pt_regs *regs) { WIND_TCB *pTcb = (WIND_TCB *)xnregistry_fetch(__xn_reg_arg1(regs)); if (!pTcb) return S_objLib_OBJ_ID_ERROR; if (taskResume((TASK_ID) pTcb) == ERROR) return wind_errnoget(); return 0; }
static int __wind_msgq_receive(struct task_struct *curr, struct pt_regs *regs) { xnhandle_t handle = __xn_reg_arg1(regs); char tmp_buf[128], *msgbuf; wind_msgq_t *msgq; int timeout, err; unsigned nbytes; nbytes = __xn_reg_arg3(regs); timeout = __xn_reg_arg4(regs); if (!__xn_access_ok(curr, VERIFY_WRITE, __xn_reg_arg2(regs), nbytes)) return -EFAULT; if (!__xn_access_ok (curr, VERIFY_WRITE, __xn_reg_arg5(regs), sizeof(nbytes))) return -EFAULT; msgq = (wind_msgq_t *)xnregistry_fetch(handle); if (!msgq) return S_objLib_OBJ_ID_ERROR; if (nbytes <= sizeof(tmp_buf)) msgbuf = tmp_buf; else { msgbuf = (char *)xnmalloc(nbytes); if (!msgbuf) return S_memLib_NOT_ENOUGH_MEMORY; } /* This is sub-optimal since we end up copying the data twice. */ err = msgQReceive((MSG_Q_ID)msgq, msgbuf, nbytes, timeout); if (err != ERROR) { __xn_copy_to_user(curr, (void __user *)__xn_reg_arg2(regs), msgbuf, err); __xn_copy_to_user(curr, (void __user *)__xn_reg_arg5(regs), &err, sizeof(err)); err = 0; } else err = wind_errnoget(); if (msgbuf != tmp_buf) xnfree(msgbuf); return err; }
static int __wind_wd_start(struct task_struct *curr, struct pt_regs *regs) { wind_rholder_t *rh; long start_server; xnhandle_t handle; wind_wd_t *wd; int timeout; spl_t s; if (!__xn_access_ok(curr, VERIFY_WRITE, __xn_reg_arg5(regs), sizeof(start_server))) return -EFAULT; handle = __xn_reg_arg1(regs); wd = (wind_wd_t *)xnregistry_fetch(handle); if (!wd) return S_objLib_OBJ_ID_ERROR; rh = wind_get_rholder(); if (wd->rh != rh) /* * User may not fiddle with watchdogs created from * other processes. */ return S_objLib_OBJ_UNAVAILABLE; timeout = __xn_reg_arg2(regs); xnlock_get_irqsave(&nklock, s); if (wdStart ((WDOG_ID)wd, timeout, (wind_timer_t) & __wind_wd_handler, (long)wd) == ERROR) { xnlock_put_irqrestore(&nklock, s); return wind_errnoget(); } wd->wdt.handler = (wind_timer_t) __xn_reg_arg3(regs); wd->wdt.arg = (long)__xn_reg_arg4(regs); start_server = rh->wdcount++ == 0; xnlock_put_irqrestore(&nklock, s); __xn_copy_to_user(curr, (void __user *)__xn_reg_arg5(regs), &start_server, sizeof(start_server)); return 0; }
static int __wind_msgq_send(struct pt_regs *regs) { xnhandle_t handle = __xn_reg_arg1(regs); char tmp_buf[128], *msgbuf; wind_msgq_t *msgq; int timeout, prio; unsigned nbytes; STATUS err; nbytes = __xn_reg_arg3(regs); timeout = __xn_reg_arg4(regs); prio = __xn_reg_arg5(regs); if (timeout != NO_WAIT && !xnpod_primary_p()) return -EPERM; msgq = (wind_msgq_t *)xnregistry_fetch(handle); if (!msgq) return S_objLib_OBJ_ID_ERROR; if (nbytes > msgq->msg_length) return S_msgQLib_INVALID_MSG_LENGTH; if (nbytes <= sizeof(tmp_buf)) msgbuf = tmp_buf; else { msgbuf = (char *)xnmalloc(nbytes); if (!msgbuf) return S_memLib_NOT_ENOUGH_MEMORY; } /* This is sub-optimal since we end up copying the data twice. */ if (__xn_safe_copy_from_user(msgbuf, (void __user *)__xn_reg_arg2(regs), nbytes)) err = -EFAULT; else { if (msgQSend((MSG_Q_ID)msgq, msgbuf, nbytes, timeout, prio) == ERROR) err = wind_errnoget(); else err = 0; } if (msgbuf != tmp_buf) xnfree(msgbuf); return err; }
static int __wind_task_verifyid(struct task_struct *curr, struct pt_regs *regs) { xnhandle_t handle = __xn_reg_arg1(regs); WIND_TCB *pTcb; pTcb = (WIND_TCB *)xnregistry_fetch(handle); if (!pTcb) return S_objLib_OBJ_ID_ERROR; if (taskIdVerify((TASK_ID) pTcb) == ERROR) return wind_errnoget(); return 0; }
static int __wind_sem_flush(struct task_struct *curr, struct pt_regs *regs) { xnhandle_t handle = __xn_reg_arg1(regs); wind_sem_t *sem; sem = (wind_sem_t *)xnregistry_fetch(handle); if (!sem) return S_objLib_OBJ_ID_ERROR; if (semFlush((SEM_ID)sem) == ERROR) return wind_errnoget(); return 0; }
static int __wind_msgq_delete(struct task_struct *curr, struct pt_regs *regs) { xnhandle_t handle = __xn_reg_arg1(regs); wind_msgq_t *msgq; msgq = (wind_msgq_t *)xnregistry_fetch(handle); if (!msgq) return S_objLib_OBJ_ID_ERROR; if (msgQDelete((MSG_Q_ID)msgq) == ERROR) return wind_errnoget(); return 0; }
static int __wind_wd_cancel(struct task_struct *curr, struct pt_regs *regs) { xnhandle_t handle = __xn_reg_arg1(regs); wind_wd_t *wd; wd = (wind_wd_t *)xnregistry_fetch(handle); if (!wd) return S_objLib_OBJ_ID_ERROR; if (wdCancel((WDOG_ID)wd) == ERROR) return wind_errnoget(); return 0; }
static int __wind_wd_create(struct pt_regs *regs) { WDOG_ID wdog_id; wind_wd_t *wd; wd = (wind_wd_t *)wdCreate(); if (!wd) return wind_errnoget(); wdog_id = wd->handle; return __xn_safe_copy_to_user((void __user *)__xn_reg_arg1(regs), &wdog_id, sizeof(wdog_id)); }
static int __wind_sem_take(struct pt_regs *regs) { xnhandle_t handle = __xn_reg_arg1(regs); int timeout = __xn_reg_arg2(regs); wind_sem_t *sem; sem = (wind_sem_t *)xnregistry_fetch(handle); if (!sem) return S_objLib_OBJ_ID_ERROR; if (semTake((SEM_ID)sem, timeout) == ERROR) return wind_errnoget(); return 0; }
static int __wind_sem_mcreate(struct pt_regs *regs) { wind_sem_t *sem; SEM_ID sem_id; int flags; flags = __xn_reg_arg1(regs); sem = (wind_sem_t *)semMCreate(flags); if (!sem) return wind_errnoget(); sem_id = sem->handle; return __xn_safe_copy_to_user((void __user *)__xn_reg_arg2(regs), &sem_id, sizeof(sem_id)); }
static int __wind_task_suspend(struct task_struct *curr, struct pt_regs *regs) { xnhandle_t handle = __xn_reg_arg1(regs); WIND_TCB *pTcb; if (handle) pTcb = (WIND_TCB *)xnregistry_fetch(handle); else pTcb = __wind_task_current(curr); if (!pTcb) return S_objLib_OBJ_ID_ERROR; if (taskSuspend((TASK_ID) pTcb) == ERROR) return wind_errnoget(); return 0; }
static int __wind_task_delete(struct pt_regs *regs) { xnhandle_t handle = __xn_reg_arg1(regs); WIND_TCB *pTcb; if (handle) pTcb = __wind_lookup_task(handle); else pTcb = __wind_task_current(current); if (!pTcb) return S_objLib_OBJ_ID_ERROR; if (taskDelete((TASK_ID) pTcb) == ERROR) return wind_errnoget(); return 0; }
static int __wind_msgq_nummsgs(struct pt_regs *regs) { xnhandle_t handle = __xn_reg_arg1(regs); wind_msgq_t *msgq; int nummsgs; msgq = (wind_msgq_t *)xnregistry_fetch(handle); if (!msgq) return S_objLib_OBJ_ID_ERROR; nummsgs = msgQNumMsgs((MSG_Q_ID)msgq); if (nummsgs == ERROR) return wind_errnoget(); return __xn_safe_copy_to_user((void __user *)__xn_reg_arg2(regs), &nummsgs, sizeof(nummsgs)); }
static int __wind_msgq_create(struct pt_regs *regs) { int nb_msgs, length, flags; wind_msgq_t *msgq; MSG_Q_ID qid; nb_msgs = __xn_reg_arg1(regs); length = __xn_reg_arg2(regs); flags = __xn_reg_arg3(regs); msgq = (wind_msgq_t *)msgQCreate(nb_msgs, length, flags); if (!msgq) return wind_errnoget(); qid = msgq->handle; return __xn_safe_copy_to_user((void __user *)__xn_reg_arg4(regs), &qid, sizeof(qid)); }
static int __wind_task_priorityget(struct pt_regs *regs) { xnhandle_t handle = __xn_reg_arg1(regs); WIND_TCB *pTcb; int prio; if (handle) pTcb = __wind_lookup_task(handle); else pTcb = __wind_task_current(current); if (!pTcb) return S_objLib_OBJ_ID_ERROR; if (taskPriorityGet((TASK_ID) pTcb, &prio) == ERROR) return wind_errnoget(); return __xn_safe_copy_to_user((void __user *)__xn_reg_arg2(regs), &prio, sizeof(prio)); }
static int __wind_errno_taskset(struct task_struct *curr, struct pt_regs *regs) { xnhandle_t handle = __xn_reg_arg1(regs); int errcode = __xn_reg_arg2(regs); WIND_TCB *pTcb; if (!handle) { wind_errnoset(errcode); return 0; } pTcb = (WIND_TCB *)xnregistry_fetch(handle); if (!pTcb) return S_objLib_OBJ_ID_ERROR; if (errnoOfTaskSet((TASK_ID) pTcb, errcode) == ERROR) return wind_errnoget(); return 0; }
static int __wind_wd_create(struct task_struct *curr, struct pt_regs *regs) { WDOG_ID wdog_id; wind_wd_t *wd; if (!__xn_access_ok (curr, VERIFY_WRITE, __xn_reg_arg1(regs), sizeof(wdog_id))) return -EFAULT; wd = (wind_wd_t *)wdCreate(); if (!wd) return wind_errnoget(); wd->rh = wind_get_rholder(); wdog_id = wd->handle; __xn_copy_to_user(curr, (void __user *)__xn_reg_arg1(regs), &wdog_id, sizeof(wdog_id)); return 0; }
static int __wind_sem_mcreate(struct task_struct *curr, struct pt_regs *regs) { wind_sem_t *sem; SEM_ID sem_id; int flags; if (!__xn_access_ok (curr, VERIFY_WRITE, __xn_reg_arg2(regs), sizeof(sem_id))) return -EFAULT; flags = __xn_reg_arg1(regs); sem = (wind_sem_t *)semMCreate(flags); if (!sem) return wind_errnoget(); sem_id = sem->handle; __xn_copy_to_user(curr, (void __user *)__xn_reg_arg2(regs), &sem_id, sizeof(sem_id)); return 0; }
static int __wind_msgq_create(struct task_struct *curr, struct pt_regs *regs) { int nb_msgs, length, flags; wind_msgq_t *msgq; MSG_Q_ID qid; if (!__xn_access_ok (curr, VERIFY_WRITE, __xn_reg_arg4(regs), sizeof(qid))) return -EFAULT; nb_msgs = __xn_reg_arg1(regs); length = __xn_reg_arg2(regs); flags = __xn_reg_arg3(regs); msgq = (wind_msgq_t *)msgQCreate(nb_msgs, length, flags); if (!msgq) return wind_errnoget(); qid = msgq->handle; __xn_copy_to_user(curr, (void __user *)__xn_reg_arg4(regs), &qid, sizeof(qid)); return 0; }
static int __wind_task_nametoid(struct pt_regs *regs) { char name[XNOBJECT_NAME_LEN]; WIND_TCB_PLACEHOLDER ph; xnhandle_t handle; if (!__xn_reg_arg1(regs)) return S_taskLib_NAME_NOT_FOUND; if (__xn_safe_strncpy_from_user(name, (const char __user *)__xn_reg_arg1(regs), sizeof(name) - 1) < 0) return -EFAULT; name[sizeof(name) - 1] = '\0'; handle = taskNameToHandle(name); if (handle == XN_NO_HANDLE) return wind_errnoget(); ph.handle = handle; /* Copy back the task handle. */ return __xn_safe_copy_to_user((void __user *)__xn_reg_arg2(regs), &ph, sizeof(ph)); }
static int __wind_task_init(struct task_struct *curr, struct pt_regs *regs) { xncompletion_t __user *u_completion; char name[XNOBJECT_NAME_LEN]; struct wind_arg_bulk bulk; int err = 0, prio, flags; WIND_TCB_PLACEHOLDER ph; WIND_TCB *task; if (!__xn_access_ok (curr, VERIFY_READ, __xn_reg_arg1(regs), sizeof(bulk))) return -EFAULT; if (!__xn_access_ok (curr, VERIFY_WRITE, __xn_reg_arg2(regs), sizeof(ph))) return -EFAULT; __xn_copy_from_user(curr, &bulk, (void __user *)__xn_reg_arg1(regs), sizeof(bulk)); if (bulk.a1) { if (!__xn_access_ok(curr, VERIFY_READ, bulk.a1, sizeof(name))) return -EFAULT; __xn_strncpy_from_user(curr, name, (const char __user *)bulk.a1, sizeof(name) - 1); name[sizeof(name) - 1] = '\0'; strncpy(curr->comm, name, sizeof(curr->comm)); curr->comm[sizeof(curr->comm) - 1] = '\0'; } else *name = '\0'; /* Task priority. */ prio = bulk.a2; /* Task flags. */ flags = bulk.a3 | VX_SHADOW; /* Completion descriptor our parent thread is pending on. */ u_completion = (xncompletion_t __user *)__xn_reg_arg3(regs); task = (WIND_TCB *)xnmalloc(sizeof(*task)); if (!task) { if (u_completion) xnshadow_signal_completion(u_completion, -ENOMEM); return -ENOMEM; } xnthread_clear_state(&task->threadbase, XNZOMBIE); /* Force FPU support in user-space. This will lead to a no-op if the platform does not support it. */ if (taskInit(task, name, prio, flags, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) == OK) { /* Let the skin discard the TCB memory upon exit. */ task->auto_delete = 1; task->ptid = bulk.a4; /* Copy back the registry handle to the ph struct. */ ph.handle = xnthread_handle(&task->threadbase); __xn_copy_to_user(curr, (void __user *)__xn_reg_arg2(regs), &ph, sizeof(ph)); err = xnshadow_map(&task->threadbase, u_completion); } else { /* Unblock and pass back error code. */ err = wind_errnoget(); if (u_completion) xnshadow_signal_completion(u_completion, err); } if (err && !xnthread_test_state(&task->threadbase, XNZOMBIE)) xnfree(task); return err; }