/kernel/trunk/generic/src/synch/waitq.c |
---|
30,7 → 30,7 |
* @file waitq.c |
* @brief Wait queue. |
* |
* Wait queue is the basic synchronization primitive upon all |
* Wait queue is the basic synchronization primitive upon which all |
* other synchronization primitives build. |
* |
* It allows threads to wait for an event in first-come, first-served |
/kernel/trunk/generic/src/smp/ipi.c |
---|
43,7 → 43,7 |
* |
* @param ipi Message to broadcast. |
* |
* @bugs The decision whether to actually send the IPI must be based |
* @bug The decision whether to actually send the IPI must be based |
* on a different criterion. The current version has |
* problems when some of the detected CPUs are marked |
* disabled in machine configuration. |
/kernel/trunk/generic/src/ddi/ddi.c |
---|
40,9 → 40,9 |
#include <proc/task.h> |
#include <security/cap.h> |
#include <mm/frame.h> |
#include <mm/page.h> |
#include <mm/as.h> |
#include <synch/spinlock.h> |
#include <syscall/copy.h> |
#include <arch.h> |
#include <align.h> |
#include <errno.h> |
183,8 → 183,12 |
__native sys_physmem_map(ddi_memarg_t *uspace_mem_arg) |
{ |
ddi_memarg_t arg; |
int rc; |
copy_from_uspace(&arg, uspace_mem_arg, sizeof(ddi_memarg_t)); |
rc = copy_from_uspace(&arg, uspace_mem_arg, sizeof(ddi_memarg_t)); |
if (rc != 0) |
return (__native) rc; |
return (__native) ddi_physmem_map((task_id_t) arg.task_id, ALIGN_DOWN((__address) arg.phys_base, FRAME_SIZE), |
ALIGN_DOWN((__address) arg.virt_base, PAGE_SIZE), (count_t) arg.pages, |
(bool) arg.writable); |
199,7 → 203,11 |
__native sys_iospace_enable(ddi_ioarg_t *uspace_io_arg) |
{ |
ddi_ioarg_t arg; |
int rc; |
copy_from_uspace(&arg, uspace_io_arg, sizeof(ddi_ioarg_t)); |
rc = copy_from_uspace(&arg, uspace_io_arg, sizeof(ddi_ioarg_t)); |
if (rc != 0) |
return (__native) rc; |
return (__native) ddi_iospace_enable((task_id_t) arg.task_id, (__address) arg.ioaddr, (size_t) arg.size); |
} |
/kernel/trunk/generic/src/printf/vsnprintf.c |
---|
39,9 → 39,9 |
int vsnprintf_write(const char *str, size_t count, struct vsnprintf_data *data); |
/** Write string to given buffer. |
* Write at most data->size characters including trailing zero. According to C99 has snprintf to return number |
* Write at most data->size characters including trailing zero. According to C99, snprintf() has to return number |
* of characters that would have been written if enough space had been available. Hence the return value is not |
* number of really printed characters but size of input string. Number of really used characters |
* number of really printed characters but size of the input string. Number of really used characters |
* is stored in data->len. |
* @param str source string to print |
* @param count size of source string |
90,5 → 90,3 |
/* vsnprintf_write ensures that str will be terminated by zero. */ |
return printf_core(fmt, &ps, ap); |
} |
/kernel/trunk/generic/src/proc/task.c |
---|
48,8 → 48,8 |
#include <memstr.h> |
#include <print.h> |
#include <elf.h> |
#include <syscall/copy.h> |
#ifndef LOADED_PROG_STACK_PAGES_NO |
#define LOADED_PROG_STACK_PAGES_NO 1 |
#endif |
170,7 → 170,7 |
* |
* @param uspace_task_id Userspace address of 8-byte buffer where to store current task ID. |
* |
* @return Always returns 0. |
* @return 0 on success or an error code from @ref errno.h. |
*/ |
__native sys_task_get_id(task_id_t *uspace_task_id) |
{ |
178,9 → 178,7 |
* No need to acquire lock on TASK because taskid |
* remains constant for the lifespan of the task. |
*/ |
copy_to_uspace(uspace_task_id, &TASK->taskid, sizeof(TASK->taskid)); |
return 0; |
return (__native) copy_to_uspace(uspace_task_id, &TASK->taskid, sizeof(TASK->taskid)); |
} |
/** Find task structure corresponding to task ID. |
/kernel/trunk/generic/src/proc/thread.c |
---|
60,6 → 60,8 |
#include <mm/slab.h> |
#include <debug.h> |
#include <main/uinit.h> |
#include <syscall/copy.h> |
#include <errno.h> |
char *thread_states[] = {"Invalid", "Running", "Sleeping", "Ready", "Entering", "Exiting"}; /**< Thread states */ |
304,6 → 306,9 |
t->sleep_queue = NULL; |
t->timeout_pending = 0; |
t->in_copy_from_uspace = false; |
t->in_copy_to_uspace = false; |
t->rwlock_holder_type = RWLOCK_NONE; |
t->task = task; |
462,11 → 467,18 |
char namebuf[THREAD_NAME_BUFLEN]; |
uspace_arg_t *kernel_uarg; |
__u32 tid; |
int rc; |
copy_from_uspace(namebuf, uspace_name, THREAD_NAME_BUFLEN); |
rc = copy_from_uspace(namebuf, uspace_name, THREAD_NAME_BUFLEN); |
if (rc != 0) |
return (__native) rc; |
kernel_uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0); |
copy_from_uspace(kernel_uarg, uspace_uarg, sizeof(uspace_arg_t)); |
rc = copy_from_uspace(kernel_uarg, uspace_uarg, sizeof(uspace_arg_t)); |
if (rc != 0) { |
free(kernel_uarg); |
return (__native) rc; |
} |
if ((t = thread_create(uinit, kernel_uarg, TASK, 0, namebuf))) { |
tid = t->tid; |
476,7 → 488,7 |
free(kernel_uarg); |
} |
return (__native) -1; |
return (__native) ENOMEM; |
} |
/** Process syscall to terminate thread. |
/kernel/trunk/generic/src/mm/slab.c |
---|
277,8 → 277,8 |
if (list_empty(&cache->partial_slabs)) { |
/* Allow recursion and reclaiming |
* - this should work, as the slab control structures |
* are small and do not need to allocte with anything |
* other ten frame_alloc when they are allocating, |
* are small and do not need to allocate with anything |
* other than frame_alloc when they are allocating, |
* that's why we should get recursion at most 1-level deep |
*/ |
spinlock_unlock(&cache->slablock); |
889,7 → 889,6 |
return slab_alloc(malloc_caches[idx], flags); |
} |
void free(void *obj) |
{ |
slab_t *slab; |
/kernel/trunk/generic/src/mm/as.c |
---|
57,6 → 57,7 |
#include <adt/list.h> |
#include <adt/btree.h> |
#include <proc/task.h> |
#include <proc/thread.h> |
#include <arch/asm.h> |
#include <panic.h> |
#include <debug.h> |
68,6 → 69,8 |
#include <config.h> |
#include <arch/types.h> |
#include <typedefs.h> |
#include <syscall/copy.h> |
#include <arch/interrupt.h> |
as_operations_t *as_operations = NULL; |
477,10 → 480,11 |
* Interrupts are assumed disabled. |
* |
* @param page Faulting page. |
* @param istate Pointer to interrupted state. |
* |
* @return 0 on page fault, 1 on success. |
* @return 0 on page fault, 1 on success or 2 if the fault was caused by copy_to_uspace() or copy_from_uspace(). |
*/ |
int as_page_fault(__address page) |
int as_page_fault(__address page, istate_t *istate) |
{ |
pte_t *pte; |
as_area_t *area; |
496,7 → 500,7 |
* Signal page fault to low-level handler. |
*/ |
spinlock_unlock(&AS->lock); |
return 0; |
goto page_fault; |
} |
if (area->attributes & AS_AREA_ATTR_PARTIAL) { |
506,7 → 510,7 |
*/ |
spinlock_unlock(&area->lock); |
spinlock_unlock(&AS->lock); |
return 0; |
goto page_fault; |
} |
ASSERT(!(area->flags & AS_AREA_DEVICE)); |
554,9 → 558,25 |
spinlock_unlock(&area->lock); |
spinlock_unlock(&AS->lock); |
return 1; |
return AS_PF_OK; |
page_fault: |
if (!THREAD) |
return AS_PF_FAULT; |
if (THREAD->in_copy_from_uspace) { |
THREAD->in_copy_from_uspace = false; |
istate_set_retaddr(istate, (__address) &memcpy_from_uspace_failover_address); |
} else if (THREAD->in_copy_to_uspace) { |
THREAD->in_copy_to_uspace = false; |
istate_set_retaddr(istate, (__address) &memcpy_to_uspace_failover_address); |
} else { |
return AS_PF_FAULT; |
} |
return AS_PF_DEFER; |
} |
/** Switch address spaces. |
* |
* @param old Old address space or NULL. |
884,8 → 904,11 |
__native sys_as_area_accept(as_area_acptsnd_arg_t *uspace_accept_arg) |
{ |
as_area_acptsnd_arg_t arg; |
int rc; |
copy_from_uspace(&arg, uspace_accept_arg, sizeof(as_area_acptsnd_arg_t)); |
rc = copy_from_uspace(&arg, uspace_accept_arg, sizeof(as_area_acptsnd_arg_t)); |
if (rc != 0) |
return rc; |
if (!arg.size) |
return (__native) EPERM; |
906,8 → 929,11 |
__native sys_as_area_send(as_area_acptsnd_arg_t *uspace_send_arg) |
{ |
as_area_acptsnd_arg_t arg; |
int rc; |
copy_from_uspace(&arg, uspace_send_arg, sizeof(as_area_acptsnd_arg_t)); |
rc = copy_from_uspace(&arg, uspace_send_arg, sizeof(as_area_acptsnd_arg_t)); |
if (rc != 0) |
return rc; |
if (!arg.size) |
return (__native) EPERM; |
/kernel/trunk/generic/src/syscall/copy.c |
---|
0,0 → 1,125 |
/* |
* Copyright (C) 2006 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/** |
* @file copy.c |
* @brief Copying between kernel and userspace. |
* |
* This file contains sanitized functions for copying data |
* between kernel and userspace. |
*/ |
#include <syscall/copy.h> |
#include <proc/thread.h> |
#include <mm/as.h> |
#include <macros.h> |
#include <arch.h> |
#include <errno.h> |
#include <typedefs.h> |
/** Copy data from userspace to kernel. |
* |
* Provisions are made to return value even after page fault. |
* |
* This function can be called only from syscall. |
* |
* @param dst Destination kernel address. |
* @param uspace_src Source userspace address. |
* @param size Size of the data to be copied. |
* |
* @return 0 on success or error code from @ref errno.h. |
*/ |
int copy_from_uspace(void *dst, void *uspace_src, size_t size) |
{ |
ipl_t ipl; |
int rc; |
ASSERT(THREAD); |
ASSERT(!THREAD->in_copy_from_uspace); |
if (!KERNEL_ADDRESS_SPACE_SHADOWED) { |
if (overlaps((__address) uspace_src, size, |
KERNEL_ADDRESS_SPACE_START, KERNEL_ADDRESS_SPACE_END-KERNEL_ADDRESS_SPACE_START)) { |
/* |
* The userspace source block conflicts with kernel address space. |
*/ |
return EPERM; |
} |
} |
ipl = interrupts_disable(); |
THREAD->in_copy_from_uspace = true; |
rc = memcpy_from_uspace(dst, uspace_src, size); |
THREAD->in_copy_from_uspace = false; |
interrupts_restore(ipl); |
return !rc ? EPERM : 0; |
} |
/** Copy data from kernel to userspace. |
* |
* Provisions are made to return value even after page fault. |
* |
* This function can be called only from syscall. |
* |
* @param uspace_dst Destination userspace address. |
* @param uspace_src Source kernel address. |
* @param size Size of the data to be copied. |
* |
* @return 0 on success or error code from @ref errno.h. |
*/ |
int copy_to_uspace(void *uspace_dst, void *src, size_t size) |
{ |
ipl_t ipl; |
int rc; |
ASSERT(THREAD); |
ASSERT(!THREAD->in_copy_from_uspace); |
if (!KERNEL_ADDRESS_SPACE_SHADOWED) { |
if (overlaps((__address) uspace_dst, size, |
KERNEL_ADDRESS_SPACE_START, KERNEL_ADDRESS_SPACE_END-KERNEL_ADDRESS_SPACE_START)) { |
/* |
* The userspace destination block conflicts with kernel address space. |
*/ |
return EPERM; |
} |
} |
ipl = interrupts_disable(); |
THREAD->in_copy_from_uspace = true; |
rc = memcpy_to_uspace(uspace_dst, src, size); |
THREAD->in_copy_from_uspace = false; |
interrupts_restore(ipl); |
return !rc ? EPERM : 0; |
} |
/kernel/trunk/generic/src/ipc/sysipc.c |
---|
28,9 → 28,8 |
#include <arch.h> |
#include <proc/task.h> |
#include <proc/thread.h> |
#include <errno.h> |
#include <mm/page.h> |
#include <memstr.h> |
#include <debug.h> |
#include <ipc/ipc.h> |
38,10 → 37,8 |
#include <ipc/irq.h> |
#include <ipc/ipcrsc.h> |
#include <arch/interrupt.h> |
#include <print.h> |
#include <arch.h> |
#include <proc/thread.h> |
#include <syscall/copy.h> |
#define GET_CHECK_PHONE(phone,phoneid,err) { \ |
if (phoneid > IPC_MAX_PHONES) { err; } \ |
228,9 → 225,12 |
call_t call; |
phone_t *phone; |
int res; |
int rc; |
ipc_call_static_init(&call); |
copy_from_uspace(&call.data.args, &question->args, sizeof(call.data.args)); |
rc = copy_from_uspace(&call.data.args, &question->args, sizeof(call.data.args)); |
if (rc != 0) |
return (__native) rc; |
GET_CHECK_PHONE(phone, phoneid, return ENOENT); |
240,7 → 240,9 |
} else |
IPC_SET_RETVAL(call.data, res); |
STRUCT_TO_USPACE(&reply->args, &call.data.args); |
rc = STRUCT_TO_USPACE(&reply->args, &call.data.args); |
if (rc != 0) |
return rc; |
return 0; |
} |
297,6 → 299,7 |
call_t *call; |
phone_t *phone; |
int res; |
int rc; |
if (check_call_limit()) |
return IPC_CALLRET_TEMPORARY; |
304,7 → 307,9 |
GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL); |
call = ipc_call_alloc(0); |
copy_from_uspace(&call->data.args, &data->args, sizeof(call->data.args)); |
rc = copy_from_uspace(&call->data.args, &data->args, sizeof(call->data.args)); |
if (rc != 0) |
return (__native) rc; |
if (!(res=request_preprocess(call))) |
ipc_call(phone, call); |
else |
393,6 → 398,7 |
call_t *call; |
ipc_data_t saved_data; |
int saveddata = 0; |
int rc; |
call = get_call(callid); |
if (!call) |
402,8 → 408,10 |
memcpy(&saved_data, &call->data, sizeof(call->data)); |
saveddata = 1; |
} |
copy_from_uspace(&call->data.args, &data->args, |
rc = copy_from_uspace(&call->data.args, &data->args, |
sizeof(call->data.args)); |
if (rc != 0) |
return rc; |
answer_preprocess(call, saveddata ? &saved_data : NULL); |
/kernel/trunk/generic/src/ipc/irq.c |
---|
47,6 → 47,7 |
#include <ipc/ipc.h> |
#include <ipc/irq.h> |
#include <atomic.h> |
#include <syscall/copy.h> |
typedef struct { |
SPINLOCK_DECLARE(lock); |
120,9 → 121,14 |
{ |
irq_code_t *code; |
irq_cmd_t *ucmds; |
int rc; |
code = malloc(sizeof(*code), 0); |
copy_from_uspace(code, ucode, sizeof(*code)); |
rc = copy_from_uspace(code, ucode, sizeof(*code)); |
if (rc != 0) { |
free(code); |
return NULL; |
} |
if (code->cmdcount > IRQ_MAX_PROG_SIZE) { |
free(code); |
130,7 → 136,12 |
} |
ucmds = code->cmds; |
code->cmds = malloc(sizeof(code->cmds[0]) * (code->cmdcount), 0); |
copy_from_uspace(code->cmds, ucmds, sizeof(code->cmds[0]) * (code->cmdcount)); |
rc = copy_from_uspace(code->cmds, ucmds, sizeof(code->cmds[0]) * (code->cmdcount)); |
if (rc != 0) { |
free(code->cmds); |
free(code); |
return NULL; |
} |
return code; |
} |