/** Syscall for creating a new loader instance from userspace. * * Creates a new task from the program loader image and sets * the task name. * * @param uspace_name Name to set on the new task (typically the same * as the command used to execute it). * @param name_len Length of the name. * * @return EOK on success or an error code from @ref errno.h. * */ sysarg_t sys_program_spawn_loader(char *uspace_name, size_t name_len) { /* Cap length of name and copy it from userspace. */ if (name_len > TASK_NAME_BUFLEN - 1) name_len = TASK_NAME_BUFLEN - 1; char namebuf[TASK_NAME_BUFLEN]; int rc = copy_from_uspace(namebuf, uspace_name, name_len); if (rc != 0) return (sysarg_t) rc; namebuf[name_len] = 0; /* Spawn the new task. */ program_t prg; rc = program_create_loader(&prg, namebuf); if (rc != 0) return rc; // FIXME: control the capabilities cap_set(prg.task, cap_get(TASK)); program_ready(&prg); return EOK; }
/** Connect an IRQ handler to a task. * * @param inr IRQ number. * @param devno Device number. * @param imethod Interface and method to be associated with the notification. * @param ucode Uspace pointer to the top-half pseudocode. * * @return EPERM or a return code returned by ipc_irq_register(). * */ sysarg_t sys_irq_register(inr_t inr, devno_t devno, sysarg_t imethod, irq_code_t *ucode) { if (!(cap_get(TASK) & CAP_IRQ_REG)) return EPERM; return ipc_irq_register(&TASK->answerbox, inr, devno, imethod, ucode); }
/** Disconnect an IRQ handler from a task. * * @param inr IRQ number. * @param devno Device number. * * @return Zero on success or EPERM on error. * */ sysarg_t sys_irq_unregister(inr_t inr, devno_t devno) { if (!(cap_get(TASK) & CAP_IRQ_REG)) return EPERM; ipc_irq_unregister(&TASK->answerbox, inr, devno); return 0; }
/** Grant capabilities to a task. * * The calling task must have the CAP_CAP capability. * * @param taskid Destination task ID. * @param caps Capabilities to grant. * * @return Zero on success or an error code from @ref errno.h. * */ static sysarg_t cap_grant(task_id_t taskid, cap_t caps) { if (!(cap_get(TASK) & CAP_CAP)) return (sysarg_t) EPERM; irq_spinlock_lock(&tasks_lock, true); task_t *task = task_find_by_id(taskid); if ((!task) || (!container_check(CONTAINER, task->container))) { irq_spinlock_unlock(&tasks_lock, true); return (sysarg_t) ENOENT; } irq_spinlock_lock(&task->lock, false); task->capabilities |= caps; irq_spinlock_unlock(&task->lock, false); irq_spinlock_unlock(&tasks_lock, true); return 0; }
/* * This example demonstrates how a pager would * share part of its capabilities on the system * with its children. * * The example includes sharing of a mutex * capability with a paged-child. */ int multi_threaded_capability_sharing_example(void) { struct capability *mutex_cap; int thread_retval; /* * We are the first pager with capabilities to * create new tasks, spaces, in its own container. */ pager_read_caps(); /* * We have all our capabilities private to us. * * If we create a new task, it won't be able to * create and use userspace mutexes, because we * hold mutex capabilities privately. * * Lets try it. */ /* * Create new thread that will attempt * a mutex operation, and die on us with a * negative return code if it fails. */ if ((err = thread_create(mutex_user_thread, 0, TC_SHARE_SPACE | TC_AS_PAGER, &ids)) < 0) { printf("mutex_user_thread creation failed.\n"); goto out_err; } /* Check on how the thread has done */ if ((err = l4_thread_wait_on(ids, &thread_retval)) < 0) { print("Waiting on thread %d failed. err = %d\n", ids->tid, err); goto out_err; } if (thread_retval == 0) { printf("Thread %d returned with success, where " "we expected failure.\n", ids->tid); goto out_err; } /* * Therefore, we share our capabilities with a * collection so that our capabilities may be also * used by them. */ /* Get our private mutex cap */ mutex_cap = cap_get(CAP_TYPE_MUTEX); /* We have ability to create and use this many mutexes */ printf("%s: We have ability to create/use %d mutexes\n", self_tid(), mutex_cap->size); /* Split it */ cap_new = cap_split(mutex_cap, 10, CAP_SPLIT_SIZE); /* * Share the split part with paged-children. * * From this point onwards, any thread we create and * manage (i.e. whose pagerid == self_tid()) will have * the ability to use mutexes, as defined by cap_new * we created. */ l4_cap_share(cap_new, CAP_SHARE_PGGROUP, self_tid()); /* * Create new thread that will attempt * a mutex operation, and die on us with a * negative return code if it fails. */ if ((err = thread_create(mutex_user_thread, 0, TC_SHARE_SPACE | TC_AS_PAGER, &ids)) < 0) { printf("mutex_user_thread creation failed.\n"); goto out_err; } /* Check on how the thread has done */ if ((err = l4_thread_wait_on(ids, &thread_retval)) < 0) { printf("Waiting on thread %d failed. err = %d\n", ids->tid, err); goto out_err; } if (thread_retval < 0) { printf("Thread %d returned with failure, where " "we expected success.\n", ids->tid); goto out_err; } out_err: BUG(); }
/* * Get current zone usage. */ rctl_qty_t cpucaps_zone_get(zone_t *zone) { return (cap_get(zone->zone_cpucap)); }
/* * Get current project usage. */ rctl_qty_t cpucaps_project_get(kproject_t *kpj) { return (cap_get(kpj->kpj_cpucap)); }