/branches/sparc/kernel/generic/src/main/kinit.c |
---|
177,6 → 177,7 |
*/ |
cap_set(programs[i].task, CAP_CAP | CAP_MEM_MANAGER | |
CAP_IO_MANAGER | CAP_PREEMPT_CONTROL | CAP_IRQ_REG); |
if (!ipc_phone_0) |
ipc_phone_0 = &programs[i].task->answerbox; |
/branches/sparc/kernel/generic/src/ipc/sysipc.c |
---|
442,9 → 442,7 |
IPC_SET_ARG5(call.data, 0); |
if (!(res = request_preprocess(&call))) { |
rc = ipc_call_sync(phone, &call); |
if (rc != EOK) |
return rc; |
ipc_call_sync(phone, &call); |
process_answer(&call); |
} else { |
IPC_SET_RETVAL(call.data, res); |
482,9 → 480,7 |
GET_CHECK_PHONE(phone, phoneid, return ENOENT); |
if (!(res = request_preprocess(&call))) { |
rc = ipc_call_sync(phone, &call); |
if (rc != EOK) |
return rc; |
ipc_call_sync(phone, &call); |
process_answer(&call); |
} else |
IPC_SET_RETVAL(call.data, res); |
/branches/sparc/kernel/generic/src/ipc/ipc.c |
---|
171,10 → 171,8 |
* |
* @param phone Destination kernel phone structure. |
* @param request Call structure with request. |
* |
* @return EOK on success or EINTR if the sleep was interrupted. |
*/ |
int ipc_call_sync(phone_t *phone, call_t *request) |
void ipc_call_sync(phone_t *phone, call_t *request) |
{ |
answerbox_t sync_box; |
184,10 → 182,7 |
request->callerbox = &sync_box; |
ipc_call(phone, request); |
if (!ipc_wait_for_call(&sync_box, SYNCH_NO_TIMEOUT, |
SYNCH_FLAGS_INTERRUPTIBLE)) |
return EINTR; |
return EOK; |
ipc_wait_for_call(&sync_box, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE); |
} |
/** Answer a message which was not dispatched and is not listed in any queue. |
200,13 → 195,6 |
call->flags |= IPC_CALL_ANSWERED; |
if (call->flags & IPC_CALL_FORWARDED) { |
if (call->caller_phone) { |
/* Demasquerade the caller phone. */ |
call->data.phone = call->caller_phone; |
} |
} |
spinlock_lock(&callerbox->lock); |
list_append(&call->link, &callerbox->answers); |
spinlock_unlock(&callerbox->lock); |
359,11 → 347,8 |
list_remove(&call->link); |
spinlock_unlock(&oldbox->lock); |
if (mode & IPC_FF_ROUTE_FROM_ME) { |
if (!call->caller_phone) |
call->caller_phone = call->data.phone; |
if (mode & IPC_FF_ROUTE_FROM_ME) |
call->data.phone = newphone; |
} |
return ipc_call(newphone, call); |
} |
592,9 → 577,8 |
tmp = tmp->next) { |
call = list_get_instance(tmp, call_t, link); |
printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun |
" A1:%" PRIun " A2:%" PRIun " A3:%" PRIun |
" A4:%" PRIun " A5:%" PRIun " Flags:%x\n", call, |
call->sender->taskid, |
" A1:%" PRIun " A2:%" PRIun " A3:%" PRIun |
" A4:%" PRIun " A5:%" PRIun " Flags:%x\n", call, call->sender->taskid, |
IPC_GET_METHOD(call->data), IPC_GET_ARG1(call->data), |
IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), |
IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), |
607,9 → 591,8 |
tmp = tmp->next) { |
call = list_get_instance(tmp, call_t, link); |
printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun |
" A1:%" PRIun " A2:%" PRIun " A3:%" PRIun |
" A4:%" PRIun " A5:%" PRIun " Flags:%x\n", call, |
call->sender->taskid, |
" A1:%" PRIun " A2:%" PRIun " A3:%" PRIun |
" A4:%" PRIun " A5:%" PRIun " Flags:%x\n", call, call->sender->taskid, |
IPC_GET_METHOD(call->data), IPC_GET_ARG1(call->data), |
IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), |
IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), |
617,12 → 600,11 |
} |
/* Print answerbox - calls */ |
printf("ABOX - ANSWERS:\n"); |
for (tmp = task->answerbox.answers.next; |
tmp != &task->answerbox.answers; |
for (tmp = task->answerbox.answers.next; tmp != &task->answerbox.answers; |
tmp = tmp->next) { |
call = list_get_instance(tmp, call_t, link); |
printf("Callid:%p M:%" PRIun " A1:%" PRIun " A2:%" PRIun |
" A3:%" PRIun " A4:%" PRIun " A5:%" PRIun " Flags:%x\n", |
" A3:%" PRIun " A4:%" PRIun " A5:%" PRIun " Flags:%x\n", |
call, IPC_GET_METHOD(call->data), IPC_GET_ARG1(call->data), |
IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data), |
IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data), |
/branches/sparc/kernel/generic/src/ipc/ipcrsc.c |
---|
170,6 → 170,7 |
int i; |
spinlock_lock(&TASK->lock); |
for (i = 0; i < IPC_MAX_PHONES; i++) { |
if (TASK->phones[i].state == IPC_PHONE_HUNGUP && |
atomic_get(&TASK->phones[i].active_calls) == 0) |
182,9 → 183,8 |
} |
spinlock_unlock(&TASK->lock); |
if (i == IPC_MAX_PHONES) |
if (i >= IPC_MAX_PHONES) |
return -1; |
return i; |
} |
/branches/sparc/kernel/generic/src/mm/as.c |
---|
111,10 → 111,11 |
/** Kernel address space. */ |
as_t *AS_KERNEL = NULL; |
static int area_flags_to_page_flags(int); |
static as_area_t *find_area_and_lock(as_t *, uintptr_t); |
static bool check_area_conflicts(as_t *, uintptr_t, size_t, as_area_t *); |
static void sh_info_remove_reference(share_info_t *); |
static int area_flags_to_page_flags(int aflags); |
static as_area_t *find_area_and_lock(as_t *as, uintptr_t va); |
static bool check_area_conflicts(as_t *as, uintptr_t va, size_t size, |
as_area_t *avoid_area); |
static void sh_info_remove_reference(share_info_t *sh_info); |
static int as_constructor(void *obj, int flags) |
{ |
152,8 → 153,7 |
/** Create address space. |
* |
* @param flags Flags that influence the way in wich the address space |
* is created. |
* @param flags Flags that influence way in wich the address space is created. |
*/ |
as_t *as_create(int flags) |
{ |
186,8 → 186,6 |
* zero), the address space can be destroyed. |
* |
* We know that we don't hold any spinlock. |
* |
* @param as Address space to be destroyed. |
*/ |
void as_destroy(as_t *as) |
{ |
259,19 → 257,19 |
* |
* The created address space area is added to the target address space. |
* |
* @param as Target address space. |
* @param flags Flags of the area memory. |
* @param size Size of area. |
* @param base Base address of area. |
* @param attrs Attributes of the area. |
* @param backend Address space area backend. NULL if no backend is used. |
* @param backend_data NULL or a pointer to an array holding two void *. |
* @param as Target address space. |
* @param flags Flags of the area memory. |
* @param size Size of area. |
* @param base Base address of area. |
* @param attrs Attributes of the area. |
* @param backend Address space area backend. NULL if no backend is used. |
* @param backend_data NULL or a pointer to an array holding two void *. |
* |
* @return Address space area on success or NULL on failure. |
* @return Address space area on success or NULL on failure. |
*/ |
as_area_t * |
as_area_create(as_t *as, int flags, size_t size, uintptr_t base, int attrs, |
mem_backend_t *backend, mem_backend_data_t *backend_data) |
mem_backend_t *backend, mem_backend_data_t *backend_data) |
{ |
ipl_t ipl; |
as_area_t *a; |
323,14 → 321,13 |
/** Find address space area and change it. |
* |
* @param as Address space. |
* @param address Virtual address belonging to the area to be changed. |
* Must be page-aligned. |
* @param size New size of the virtual memory block starting at |
* address. |
* @param flags Flags influencing the remap operation. Currently unused. |
* @param as Address space. |
* @param address Virtual address belonging to the area to be changed. Must be |
* page-aligned. |
* @param size New size of the virtual memory block starting at address. |
* @param flags Flags influencing the remap operation. Currently unused. |
* |
* @return Zero on success or a value from @ref errno.h otherwise. |
* @return Zero on success or a value from @ref errno.h otherwise. |
*/ |
int as_area_resize(as_t *as, uintptr_t address, size_t size, int flags) |
{ |
438,10 → 435,8 |
cond = false; /* we are almost done */ |
i = (start_free - b) >> PAGE_WIDTH; |
if (!used_space_remove(area, start_free, |
c - i)) |
panic("Could not remove used " |
"space.\n"); |
if (!used_space_remove(area, start_free, c - i)) |
panic("Could not remove used space.\n"); |
} else { |
/* |
* The interval of used space can be |
448,8 → 443,7 |
* completely removed. |
*/ |
if (!used_space_remove(area, b, c)) |
panic("Could not remove used " |
"space.\n"); |
panic("Could not remove used space.\n"); |
} |
for (; i < c; i++) { |
511,10 → 505,10 |
/** Destroy address space area. |
* |
* @param as Address space. |
* @param address Address within the area to be deleted. |
* @param as Address space. |
* @param address Address withing the area to be deleted. |
* |
* @return Zero on success or a value from @ref errno.h on failure. |
* @return Zero on success or a value from @ref errno.h on failure. |
*/ |
int as_area_destroy(as_t *as, uintptr_t address) |
{ |
611,19 → 605,18 |
* sh_info of the source area. The process of duplicating the |
* mapping is done through the backend share function. |
* |
* @param src_as Pointer to source address space. |
* @param src_base Base address of the source address space area. |
* @param acc_size Expected size of the source area. |
* @param dst_as Pointer to destination address space. |
* @param dst_base Target base address. |
* @param src_as Pointer to source address space. |
* @param src_base Base address of the source address space area. |
* @param acc_size Expected size of the source area. |
* @param dst_as Pointer to destination address space. |
* @param dst_base Target base address. |
* @param dst_flags_mask Destination address space area flags mask. |
* |
* @return Zero on success or ENOENT if there is no such task or if |
* there is no such address space area, EPERM if there was |
* a problem in accepting the area or ENOMEM if there was a |
* problem in allocating destination address space area. |
* ENOTSUP is returned if the address space area backend |
* does not support sharing. |
* @return Zero on success or ENOENT if there is no such task or if there is no |
* such address space area, EPERM if there was a problem in accepting the area |
* or ENOMEM if there was a problem in allocating destination address space |
* area. ENOTSUP is returned if the address space area backend does not support |
* sharing. |
*/ |
int as_area_share(as_t *src_as, uintptr_t src_base, size_t acc_size, |
as_t *dst_as, uintptr_t dst_base, int dst_flags_mask) |
742,11 → 735,10 |
* |
* The address space area must be locked prior to this call. |
* |
* @param area Address space area. |
* @param access Access mode. |
* @param area Address space area. |
* @param access Access mode. |
* |
* @return False if access violates area's permissions, true |
* otherwise. |
* @return False if access violates area's permissions, true otherwise. |
*/ |
bool as_area_check_access(as_area_t *area, pf_access_t access) |
{ |
762,7 → 754,7 |
return true; |
} |
/** Change adress space area flags. |
/** Change adress area flags. |
* |
* The idea is to have the same data, but with a different access mode. |
* This is needed e.g. for writing code into memory and then executing it. |
769,11 → 761,11 |
* In order for this to work properly, this may copy the data |
* into private anonymous memory (unless it's already there). |
* |
* @param as Address space. |
* @param flags Flags of the area memory. |
* @param address Address withing the area to be changed. |
* @param as Address space. |
* @param flags Flags of the area memory. |
* @param address Address withing the area to be changed. |
* |
* @return Zero on success or a value from @ref errno.h on failure. |
* @return Zero on success or a value from @ref errno.h on failure. |
*/ |
int as_area_change_flags(as_t *as, int flags, uintptr_t address) |
{ |
878,14 → 870,9 |
tlb_shootdown_finalize(); |
/* |
* Set the new flags. |
*/ |
area->flags = flags; |
/* |
* Map pages back in with new flags. This step is kept separate |
* so that the memory area could not be accesed with both the old and |
* the new flags at once. |
* so that there's no instant when the memory area could be |
* accesed with both the old and the new flags at once. |
*/ |
frame_idx = 0; |
923,20 → 910,19 |
/** Handle page fault within the current address space. |
* |
* This is the high-level page fault handler. It decides whether the page fault |
* can be resolved by any backend and if so, it invokes the backend to resolve |
* the page fault. |
* This is the high-level page fault handler. It decides |
* whether the page fault can be resolved by any backend |
* and if so, it invokes the backend to resolve the page |
* fault. |
* |
* Interrupts are assumed disabled. |
* |
* @param page Faulting page. |
* @param access Access mode that caused the page fault (i.e. |
* read/write/exec). |
* @param istate Pointer to the interrupted state. |
* @param page Faulting page. |
* @param access Access mode that caused the fault (i.e. read/write/exec). |
* @param istate Pointer to interrupted state. |
* |
* @return AS_PF_FAULT on page fault, AS_PF_OK on success or |
* AS_PF_DEFER if the fault was caused by copy_to_uspace() |
* or copy_from_uspace(). |
* @return AS_PF_FAULT on page fault, AS_PF_OK on success or AS_PF_DEFER if the |
* fault was caused by copy_to_uspace() or copy_from_uspace(). |
*/ |
int as_page_fault(uintptr_t page, pf_access_t access, istate_t *istate) |
{ |
982,8 → 968,9 |
page_table_lock(AS, false); |
/* |
* To avoid race condition between two page faults on the same address, |
* we need to make sure the mapping has not been already inserted. |
* To avoid race condition between two page faults |
* on the same address, we need to make sure |
* the mapping has not been already inserted. |
*/ |
if ((pte = page_mapping_find(AS, page))) { |
if (PTE_PRESENT(pte)) { |
1037,8 → 1024,8 |
* |
* When this function is enetered, no spinlocks may be held. |
* |
* @param old Old address space or NULL. |
* @param new New address space. |
* @param old Old address space or NULL. |
* @param new New address space. |
*/ |
void as_switch(as_t *old_as, as_t *new_as) |
{ |
1109,9 → 1096,9 |
/** Convert address space area flags to page flags. |
* |
* @param aflags Flags of some address space area. |
* @param aflags Flags of some address space area. |
* |
* @return Flags to be passed to page_mapping_insert(). |
* @return Flags to be passed to page_mapping_insert(). |
*/ |
int area_flags_to_page_flags(int aflags) |
{ |
1139,9 → 1126,9 |
* The address space area must be locked. |
* Interrupts must be disabled. |
* |
* @param a Address space area. |
* @param a Address space area. |
* |
* @return Flags to be used in page_mapping_insert(). |
* @return Flags to be used in page_mapping_insert(). |
*/ |
int as_area_get_flags(as_area_t *a) |
{ |
1150,13 → 1137,12 |
/** Create page table. |
* |
* Depending on architecture, create either address space private or global page |
* table. |
* Depending on architecture, create either address space |
* private or global page table. |
* |
* @param flags Flags saying whether the page table is for the kernel |
* address space. |
* @param flags Flags saying whether the page table is for kernel address space. |
* |
* @return First entry of the page table. |
* @return First entry of the page table. |
*/ |
pte_t *page_table_create(int flags) |
{ |
1170,7 → 1156,7 |
* |
* Destroy page table in architecture specific way. |
* |
* @param page_table Physical address of PTL0. |
* @param page_table Physical address of PTL0. |
*/ |
void page_table_destroy(pte_t *page_table) |
{ |
1189,8 → 1175,8 |
* prior to this call. Address space can be locked prior to this |
* call in which case the lock argument is false. |
* |
* @param as Address space. |
* @param lock If false, do not attempt to lock as->lock. |
* @param as Address space. |
* @param lock If false, do not attempt to lock as->lock. |
*/ |
void page_table_lock(as_t *as, bool lock) |
{ |
1202,8 → 1188,8 |
/** Unlock page table. |
* |
* @param as Address space. |
* @param unlock If false, do not attempt to unlock as->lock. |
* @param as Address space. |
* @param unlock If false, do not attempt to unlock as->lock. |
*/ |
void page_table_unlock(as_t *as, bool unlock) |
{ |
1218,11 → 1204,11 |
* |
* The address space must be locked and interrupts must be disabled. |
* |
* @param as Address space. |
* @param va Virtual address. |
* @param as Address space. |
* @param va Virtual address. |
* |
* @return Locked address space area containing va on success or |
* NULL on failure. |
* @return Locked address space area containing va on success or NULL on |
* failure. |
*/ |
as_area_t *find_area_and_lock(as_t *as, uintptr_t va) |
{ |
1274,15 → 1260,15 |
* |
* The address space must be locked and interrupts must be disabled. |
* |
* @param as Address space. |
* @param va Starting virtual address of the area being tested. |
* @param size Size of the area being tested. |
* @param avoid_area Do not touch this area. |
* @param as Address space. |
* @param va Starting virtual address of the area being tested. |
* @param size Size of the area being tested. |
* @param avoid_area Do not touch this area. |
* |
* @return True if there is no conflict, false otherwise. |
* @return True if there is no conflict, false otherwise. |
*/ |
bool |
check_area_conflicts(as_t *as, uintptr_t va, size_t size, as_area_t *avoid_area) |
bool check_area_conflicts(as_t *as, uintptr_t va, size_t size, |
as_area_t *avoid_area) |
{ |
as_area_t *a; |
btree_node_t *leaf, *node; |
1371,7 → 1357,7 |
ipl = interrupts_disable(); |
src_area = find_area_and_lock(AS, base); |
if (src_area) { |
if (src_area){ |
size = src_area->pages * PAGE_SIZE; |
mutex_unlock(&src_area->lock); |
} else { |
1385,11 → 1371,11 |
* |
* The address space area must be already locked. |
* |
* @param a Address space area. |
* @param page First page to be marked. |
* @param count Number of page to be marked. |
* @param a Address space area. |
* @param page First page to be marked. |
* @param count Number of page to be marked. |
* |
* @return Zero on failure and non-zero on success. |
* @return 0 on failure and 1 on success. |
*/ |
int used_space_insert(as_area_t *a, uintptr_t page, count_t count) |
{ |
1659,8 → 1645,8 |
} |
} |
panic("Inconsistency detected while adding %" PRIc " pages of used " |
"space at %p.\n", count, page); |
panic("Inconsistency detected while adding %" PRIc " pages of used space at " |
"%p.\n", count, page); |
} |
/** Mark portion of address space area as unused. |
1667,11 → 1653,11 |
* |
* The address space area must be already locked. |
* |
* @param a Address space area. |
* @param page First page to be marked. |
* @param count Number of page to be marked. |
* @param a Address space area. |
* @param page First page to be marked. |
* @param count Number of page to be marked. |
* |
* @return Zero on failure and non-zero on success. |
* @return 0 on failure and 1 on success. |
*/ |
int used_space_remove(as_area_t *a, uintptr_t page, count_t count) |
{ |
1838,8 → 1824,8 |
} |
error: |
panic("Inconsistency detected while removing %" PRIc " pages of used " |
"space from %p.\n", count, page); |
panic("Inconsistency detected while removing %" PRIc " pages of used space " |
"from %p.\n", count, page); |
} |
/** Remove reference to address space area share info. |
1846,7 → 1832,7 |
* |
* If the reference count drops to 0, the sh_info is deallocated. |
* |
* @param sh_info Pointer to address space area share info. |
* @param sh_info Pointer to address space area share info. |
*/ |
void sh_info_remove_reference(share_info_t *sh_info) |
{ |
1915,7 → 1901,7 |
/** Print out information about address space. |
* |
* @param as Address space. |
* @param as Address space. |
*/ |
void as_print(as_t *as) |
{ |
1937,9 → 1923,9 |
as_area_t *area = node->value[i]; |
mutex_lock(&area->lock); |
printf("as_area: %p, base=%p, pages=%" PRIc |
" (%p - %p)\n", area, area->base, area->pages, |
area->base, area->base + FRAMES2SIZE(area->pages)); |
printf("as_area: %p, base=%p, pages=%" PRIc " (%p - %p)\n", |
area, area->base, area->pages, area->base, |
area->base + FRAMES2SIZE(area->pages)); |
mutex_unlock(&area->lock); |
} |
} |
/branches/sparc/kernel/generic/src/mm/backend_elf.c |
---|
118,7 → 118,7 |
*/ |
for (i = 0; i < leaf->keys; i++) { |
if (leaf->key[i] == page - area->base) { |
if (leaf->key[i] == page) { |
found = true; |
break; |
} |
/branches/sparc/kernel/generic/src/mm/backend_anon.c |
---|
78,6 → 78,7 |
int anon_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access) |
{ |
uintptr_t frame; |
bool dirty = false; |
if (!as_area_check_access(area, access)) |
return AS_PF_FAULT; |
105,7 → 106,7 |
*/ |
for (i = 0; i < leaf->keys; i++) { |
if (leaf->key[i] == |
ALIGN_DOWN(addr, PAGE_SIZE) - area->base) { |
ALIGN_DOWN(addr, PAGE_SIZE)) { |
allocate = false; |
break; |
} |
113,6 → 114,7 |
if (allocate) { |
frame = (uintptr_t) frame_alloc(ONE_FRAME, 0); |
memsetb((void *) PA2KA(frame), FRAME_SIZE, 0); |
dirty = true; |
/* |
* Insert the address of the newly allocated |
143,6 → 145,7 |
*/ |
frame = (uintptr_t) frame_alloc(ONE_FRAME, 0); |
memsetb((void *) PA2KA(frame), FRAME_SIZE, 0); |
dirty = true; |
} |
/* |
/branches/sparc/kernel/generic/src/proc/task.c |
---|
71,7 → 71,11 |
static task_id_t task_counter = 0; |
/** Initialize kernel tasks support. */ |
/** Initialize tasks |
* |
* Initialize kernel tasks support. |
* |
*/ |
void task_init(void) |
{ |
TASK = NULL; |
79,8 → 83,7 |
} |
/* |
* The idea behind this walker is to remember a single task different from |
* TASK. |
* The idea behind this walker is to remember a single task different from TASK. |
*/ |
static bool task_done_walker(avltree_node_t *node, void *arg) |
{ |
95,7 → 98,9 |
return true; /* continue the walk */ |
} |
/** Kill all tasks except the current task. */ |
/** Kill all tasks except the current task. |
* |
*/ |
void task_done(void) |
{ |
task_t *t; |
127,13 → 132,15 |
} while (t != NULL); |
} |
/** Create new task with no threads. |
/** Create new task |
* |
* @param as Task's address space. |
* @param name Symbolic name. |
* Create new task with no threads. |
* |
* @return New task's structure. |
* @param as Task's address space. |
* @param name Symbolic name. |
* |
* @return New task's structure |
* |
*/ |
task_t *task_create(as_t *as, char *name) |
{ |
187,7 → 194,7 |
/** Destroy task. |
* |
* @param t Task to be destroyed. |
* @param t Task to be destroyed. |
*/ |
void task_destroy(task_t *t) |
{ |
220,16 → 227,16 |
/** Syscall for reading task ID from userspace. |
* |
* @param uspace_task_id userspace address of 8-byte buffer |
* where to store current task ID. |
* @param uspace_task_id Userspace address of 8-byte buffer where to store |
* current task ID. |
* |
* @return Zero on success or an error code from @ref errno.h. |
* @return 0 on success or an error code from @ref errno.h. |
*/ |
unative_t sys_task_get_id(task_id_t *uspace_task_id) |
{ |
/* |
* No need to acquire lock on TASK because taskid remains constant for |
* the lifespan of the task. |
* No need to acquire lock on TASK because taskid |
* remains constant for the lifespan of the task. |
*/ |
return (unative_t) copy_to_uspace(uspace_task_id, &TASK->taskid, |
sizeof(TASK->taskid)); |
237,15 → 244,16 |
/** Find task structure corresponding to task ID. |
* |
* The tasks_lock must be already held by the caller of this function and |
* interrupts must be disabled. |
* The tasks_lock must be already held by the caller of this function |
* and interrupts must be disabled. |
* |
* @param id Task ID. |
* @param id Task ID. |
* |
* @return Task structure address or NULL if there is no such task |
* ID. |
* @return Task structure address or NULL if there is no such task ID. |
*/ |
task_t *task_find_by_id(task_id_t id) { avltree_node_t *node; |
task_t *task_find_by_id(task_id_t id) |
{ |
avltree_node_t *node; |
node = avltree_search(&tasks_tree, (avltree_key_t) id); |
256,13 → 264,11 |
/** Get accounting data of given task. |
* |
* Note that task lock of 't' must be already held and interrupts must be |
* already disabled. |
* Note that task lock of 't' must be already held and |
* interrupts must be already disabled. |
* |
* @param t Pointer to thread. |
* @param t Pointer to thread. |
* |
* @return Number of cycles used by the task and all its threads |
* so far. |
*/ |
uint64_t task_get_accounting(task_t *t) |
{ |
294,9 → 300,9 |
* This function is idempotent. |
* It signals all the task's threads to bail it out. |
* |
* @param id ID of the task to be killed. |
* @param id ID of the task to be killed. |
* |
* @return Zero on success or an error code from errno.h. |
* @return 0 on success or an error code from errno.h |
*/ |
int task_kill(task_id_t id) |
{ |
317,7 → 323,7 |
spinlock_unlock(&tasks_lock); |
/* |
* Interrupt all threads. |
* Interrupt all threads except ktaskclnp. |
*/ |
spinlock_lock(&ta->lock); |
for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) { |
/branches/sparc/kernel/generic/include/ipc/ipc.h |
---|
281,13 → 281,6 |
/** Buffer for IPC_M_DATA_WRITE and IPC_M_DATA_READ. */ |
uint8_t *buffer; |
/* |
* The forward operation can masquerade the caller phone. For those |
* cases, we must keep it aside so that the answer is processed |
* correctly. |
*/ |
phone_t *caller_phone; |
} call_t; |
extern void ipc_init(void); |
294,7 → 287,7 |
extern call_t * ipc_wait_for_call(answerbox_t *, uint32_t, int); |
extern void ipc_answer(answerbox_t *, call_t *); |
extern int ipc_call(phone_t *, call_t *); |
extern int ipc_call_sync(phone_t *, call_t *); |
extern void ipc_call_sync(phone_t *, call_t *); |
extern void ipc_phone_init(phone_t *); |
extern void ipc_phone_connect(phone_t *, answerbox_t *); |
extern void ipc_call_free(call_t *); |
/branches/sparc/kernel/generic/include/errno.h |
---|
56,7 → 56,6 |
#define EINVAL -13 /* Invalid value */ |
#define EBUSY -14 /* Resource is busy */ |
#define EOVERFLOW -15 /* The result does not fit its size. */ |
#define EINTR -16 /* Operation was interrupted. */ |
#endif |
/branches/sparc/kernel/arch/sparc64/Makefile.inc |
---|
29,15 → 29,11 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_NAME = elf64-sparc |
BFD_ARCH = sparc |
BFD = binary |
TARGET = sparc64-linux-gnu |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/sparc64 |
TOOLCHAIN_DIR = /usr/local/sparc64 |
GCC_CFLAGS += -m64 -mcpu=ultrasparc |
SUNCC_CFLAGS += -m64 -xarch=sparc -xregs=appl,no%float |
/branches/sparc/kernel/arch/sparc64/include/atomic.h |
---|
37,7 → 37,6 |
#include <arch/barrier.h> |
#include <arch/types.h> |
#include <preemption.h> |
/** Atomic add operation. |
* |
57,8 → 56,7 |
a = *((uint64_t *) x); |
b = a + i; |
asm volatile ("casx %0, %2, %1\n" : "+m" (*((uint64_t *)x)), |
"+r" (b) : "r" (a)); |
asm volatile ("casx %0, %2, %1\n" : "+m" (*((uint64_t *)x)), "+r" (b) : "r" (a)); |
} while (a != b); |
return a; |
99,8 → 97,7 |
uint64_t v = 1; |
volatile uintptr_t x = (uint64_t) &val->count; |
asm volatile ("casx %0, %2, %1\n" : "+m" (*((uint64_t *) x)), |
"+r" (v) : "r" (0)); |
asm volatile ("casx %0, %2, %1\n" : "+m" (*((uint64_t *) x)), "+r" (v) : "r" (0)); |
return v; |
} |
112,8 → 109,6 |
volatile uintptr_t x = (uint64_t) &val->count; |
preemption_disable(); |
asm volatile ( |
"0:\n" |
"casx %0, %3, %1\n" |
/branches/sparc/kernel/arch/ia64/Makefile.inc |
---|
29,15 → 29,14 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_NAME = elf64-little |
BFD_ARCH = ia64-elf64 |
TARGET = ia64-pc-linux-gnu |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ia64 |
TOOLCHAIN_DIR = /usr/local/ia64 |
INIT0_ADDRESS = 0xe000000004404000 |
INIT0_SIZE = 0x100000 |
CMN1 = -mconstant-gp -fno-unwind-tables -mfixed-range=f32-f127 |
GCC_CFLAGS += $(CMN1) |
ICC_CFLAGS += $(CMN1) |
45,8 → 44,9 |
LFLAGS += -EL |
AFLAGS += -mconstant-gp |
DEFS += -D__64_BITS__ -D$(MACHINE) |
DEFS += -D__64_BITS__ -DINIT0_ADDRESS=$(INIT0_ADDRESS) -DINIT0_SIZE=$(INIT0_SIZE) -D$(MACHINE) |
## Compile with page hash table support. |
# |
96,5 → 96,6 |
CONFIG_I8042 = y |
DEFS += -DI460GX -DCONFIG_I8042 |
BFD = binary |
endif |
/branches/sparc/kernel/arch/arm32/Makefile.inc |
---|
29,15 → 29,11 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_NAME = elf32-littlearm |
BFD_ARCH = arm |
BFD = binary |
TARGET = arm-linux-gnu |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/arm |
TOOLCHAIN_DIR = /usr/local/arm |
KERNEL_LOAD_ADDRESS = 0x80200000 |
/branches/sparc/kernel/arch/ia32xen/Makefile.inc |
---|
29,15 → 29,11 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_NAME = elf32-i386 |
BFD_ARCH = i386 |
BFD = elf32-i386 |
TARGET = i686-pc-linux-gnu |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/i686 |
TOOLCHAIN_DIR = /usr/local/i686 |
DEFS += -DMACHINE=$(MACHINE) -D__32_BITS__ |
/branches/sparc/kernel/arch/amd64/include/atomic.h |
---|
108,13 → 108,13 |
#endif |
"mov %0, %1\n" |
"testq %1, %1\n" |
"jnz 0b\n" /* lightweight looping on locked spinlock */ |
"jnz 0b\n" /* Lightweight looping on locked spinlock */ |
"incq %1\n" /* now use the atomic operation */ |
"xchgq %0, %1\n" |
"testq %1, %1\n" |
"jnz 0b\n" |
: "+m" (val->count), "=&r" (tmp) |
: "+m" (val->count), "=r"(tmp) |
); |
/* |
* Prevent critical section code from bleeding out this way up. |
/branches/sparc/kernel/arch/amd64/Makefile.inc |
---|
29,15 → 29,11 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_NAME = elf64-x86-64 |
BFD_ARCH = i386:x86-64 |
BFD = binary |
TARGET = amd64-linux-gnu |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/amd64 |
TOOLCHAIN_DIR = /usr/local/amd64 |
FPU_NO_CFLAGS = -mno-sse -mno-sse2 |
CMN1 = -m64 -mcmodel=kernel -mno-red-zone -fno-unwind-tables |
/branches/sparc/kernel/arch/mips32/src/mm/tlb.c |
---|
47,14 → 47,15 |
#include <align.h> |
#include <interrupt.h> |
static void tlb_refill_fail(istate_t *); |
static void tlb_invalid_fail(istate_t *); |
static void tlb_modified_fail(istate_t *); |
static void tlb_refill_fail(istate_t *istate); |
static void tlb_invalid_fail(istate_t *istate); |
static void tlb_modified_fail(istate_t *istate); |
static pte_t *find_mapping_and_check(uintptr_t, int, istate_t *, int *); |
static pte_t *find_mapping_and_check(uintptr_t badvaddr, int access, istate_t *istate, int *pfrc); |
/** Initialize TLB. |
/** Initialize TLB |
* |
* Initialize TLB. |
* Invalidate all entries and mark wired entries. |
*/ |
void tlb_arch_init(void) |
80,9 → 81,11 |
cp0_wired_write(TLB_WIRED); |
} |
/** Process TLB Refill Exception. |
/** Process TLB Refill Exception |
* |
* @param istate Interrupted register context. |
* Process TLB Refill Exception. |
* |
* @param istate Interrupted register context. |
*/ |
void tlb_refill(istate_t *istate) |
{ |
125,14 → 128,13 |
pte->a = 1; |
tlb_prepare_entry_hi(&hi, asid, badvaddr); |
tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable, |
pte->pfn); |
tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable, pte->pfn); |
/* |
* New entry is to be inserted into TLB |
*/ |
cp0_entry_hi_write(hi.value); |
if ((badvaddr / PAGE_SIZE) % 2 == 0) { |
if ((badvaddr/PAGE_SIZE) % 2 == 0) { |
cp0_entry_lo0_write(lo.value); |
cp0_entry_lo1_write(0); |
} |
151,9 → 153,11 |
tlb_refill_fail(istate); |
} |
/** Process TLB Invalid Exception. |
/** Process TLB Invalid Exception |
* |
* @param istate Interrupted register context. |
* Process TLB Invalid Exception. |
* |
* @param istate Interrupted register context. |
*/ |
void tlb_invalid(istate_t *istate) |
{ |
213,13 → 217,12 |
*/ |
pte->a = 1; |
tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable, |
pte->pfn); |
tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable, pte->pfn); |
/* |
* The entry is to be updated in TLB. |
*/ |
if ((badvaddr / PAGE_SIZE) % 2 == 0) |
if ((badvaddr/PAGE_SIZE) % 2 == 0) |
cp0_entry_lo0_write(lo.value); |
else |
cp0_entry_lo1_write(lo.value); |
234,9 → 237,11 |
tlb_invalid_fail(istate); |
} |
/** Process TLB Modified Exception. |
/** Process TLB Modified Exception |
* |
* @param istate Interrupted register context. |
* Process TLB Modified Exception. |
* |
* @param istate Interrupted register context. |
*/ |
void tlb_modified(istate_t *istate) |
{ |
287,6 → 292,12 |
} |
/* |
* Fail if the page is not writable. |
*/ |
if (!pte->w) |
goto fail; |
/* |
* Read the faulting TLB entry. |
*/ |
tlbr(); |
297,13 → 308,12 |
pte->a = 1; |
pte->d = 1; |
tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->w, pte->cacheable, |
pte->pfn); |
tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->w, pte->cacheable, pte->pfn); |
/* |
* The entry is to be updated in TLB. |
*/ |
if ((badvaddr / PAGE_SIZE) % 2 == 0) |
if ((badvaddr/PAGE_SIZE) % 2 == 0) |
cp0_entry_lo0_write(lo.value); |
else |
cp0_entry_lo1_write(lo.value); |
330,10 → 340,8 |
if (s) |
sym2 = s; |
fault_if_from_uspace(istate, "TLB Refill Exception on %p", |
cp0_badvaddr_read()); |
panic("%x: TLB Refill Exception at %x(%s<-%s)\n", cp0_badvaddr_read(), |
istate->epc, symbol, sym2); |
fault_if_from_uspace(istate, "TLB Refill Exception on %p", cp0_badvaddr_read()); |
panic("%x: TLB Refill Exception at %x(%s<-%s)\n", cp0_badvaddr_read(), istate->epc, symbol, sym2); |
} |
344,10 → 352,8 |
char *s = get_symtab_entry(istate->epc); |
if (s) |
symbol = s; |
fault_if_from_uspace(istate, "TLB Invalid Exception on %p", |
cp0_badvaddr_read()); |
panic("%x: TLB Invalid Exception at %x(%s)\n", cp0_badvaddr_read(), |
istate->epc, symbol); |
fault_if_from_uspace(istate, "TLB Invalid Exception on %p", cp0_badvaddr_read()); |
panic("%x: TLB Invalid Exception at %x(%s)\n", cp0_badvaddr_read(), istate->epc, symbol); |
} |
void tlb_modified_fail(istate_t *istate) |
357,27 → 363,23 |
char *s = get_symtab_entry(istate->epc); |
if (s) |
symbol = s; |
fault_if_from_uspace(istate, "TLB Modified Exception on %p", |
cp0_badvaddr_read()); |
panic("%x: TLB Modified Exception at %x(%s)\n", cp0_badvaddr_read(), |
istate->epc, symbol); |
fault_if_from_uspace(istate, "TLB Modified Exception on %p", cp0_badvaddr_read()); |
panic("%x: TLB Modified Exception at %x(%s)\n", cp0_badvaddr_read(), istate->epc, symbol); |
} |
/** Try to find PTE for faulting address. |
/** Try to find PTE for faulting address |
* |
* Try to find PTE for faulting address. |
* The AS->lock must be held on entry to this function. |
* |
* @param badvaddr Faulting virtual address. |
* @param access Access mode that caused the fault. |
* @param istate Pointer to interrupted state. |
* @param pfrc Pointer to variable where as_page_fault() return code |
* will be stored. |
* @param badvaddr Faulting virtual address. |
* @param access Access mode that caused the fault. |
* @param istate Pointer to interrupted state. |
* @param pfrc Pointer to variable where as_page_fault() return code will be stored. |
* |
* @return PTE on success, NULL otherwise. |
* @return PTE on success, NULL otherwise. |
*/ |
pte_t * |
find_mapping_and_check(uintptr_t badvaddr, int access, istate_t *istate, |
int *pfrc) |
pte_t *find_mapping_and_check(uintptr_t badvaddr, int access, istate_t *istate, int *pfrc) |
{ |
entry_hi_t hi; |
pte_t *pte; |
396,7 → 398,7 |
* Check if the mapping exists in page tables. |
*/ |
pte = page_mapping_find(AS, badvaddr); |
if (pte && pte->p && (pte->w || access != PF_ACCESS_WRITE)) { |
if (pte && pte->p) { |
/* |
* Mapping found in page tables. |
* Immediately succeed. |
419,7 → 421,6 |
page_table_lock(AS, true); |
pte = page_mapping_find(AS, badvaddr); |
ASSERT(pte && pte->p); |
ASSERT(pte->w || access != PF_ACCESS_WRITE); |
return pte; |
break; |
case AS_PF_DEFER: |
440,9 → 441,7 |
} |
} |
void |
tlb_prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, |
uintptr_t pfn) |
void tlb_prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, uintptr_t pfn) |
{ |
lo->value = 0; |
lo->g = g; |
481,10 → 480,10 |
lo1.value = cp0_entry_lo1_read(); |
printf("%-2u %-4u %#6x %#4x %1u %1u %1u %1u %#6x\n", |
i, hi.asid, hi.vpn2, mask.mask, |
lo0.g, lo0.v, lo0.d, lo0.c, lo0.pfn); |
i, hi.asid, hi.vpn2, mask.mask, |
lo0.g, lo0.v, lo0.d, lo0.c, lo0.pfn); |
printf(" %1u %1u %1u %1u %#6x\n", |
lo1.g, lo1.v, lo1.d, lo1.c, lo1.pfn); |
lo1.g, lo1.v, lo1.d, lo1.c, lo1.pfn); |
} |
cp0_entry_hi_write(hi_save.value); |
561,12 → 560,11 |
cp0_entry_hi_write(hi_save.value); |
} |
/** Invalidate TLB entries for specified page range belonging to specified |
* address space. |
/** Invalidate TLB entries for specified page range belonging to specified address space. |
* |
* @param asid Address space identifier. |
* @param page First page whose TLB entry is to be invalidated. |
* @param cnt Number of entries to invalidate. |
* @param asid Address space identifier. |
* @param page First page whose TLB entry is to be invalidated. |
* @param cnt Number of entries to invalidate. |
*/ |
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt) |
{ |
590,10 → 588,7 |
index.value = cp0_index_read(); |
if (!index.p) { |
/* |
* Entry was found, index register contains valid |
* index. |
*/ |
/* Entry was found, index register contains valid index. */ |
tlbr(); |
lo0.value = cp0_entry_lo0_read(); |
/branches/sparc/kernel/arch/mips32/Makefile.inc |
---|
29,19 → 29,17 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_ARCH = mips |
TARGET = mipsel-linux-gnu |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mipsel |
TOOLCHAIN_DIR = /usr/local/mipsel |
KERNEL_LOAD_ADDRESS = 0x80100000 |
INIT_ADDRESS = 0x81000000 |
INIT_SIZE = 262144 |
GCC_CFLAGS += -mno-abicalls -G 0 -fno-zero-initialized-in-bss |
DEFS += -D__32_BITS__ -DMACHINE=$(MACHINE) -DKERNEL_LOAD_ADDRESS=${KERNEL_LOAD_ADDRESS} |
DEFS += -D__32_BITS__ -DMACHINE=$(MACHINE) -DKERNEL_LOAD_ADDRESS=${KERNEL_LOAD_ADDRESS} -DINIT_ADDRESS=${INIT_ADDRESS} -DINIT_SIZE=${INIT_SIZE} |
## Compile with hierarchical page tables support. |
# |
67,8 → 65,9 |
BFD_NAME = elf32-bigmips |
BFD = ecoff-bigmips |
TARGET = mips-sgi-irix5 |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mips/bin |
TOOLCHAIN_DIR = /usr/local/mips/bin |
GCC_CFLAGS += -EB -DBIG_ENDIAN -DARCH_HAS_FPU -mips3 |
INIT_ADDRESS = 0x81800000 |
endif |
ifeq ($(MACHINE),simics) |
# SIMICS 4kc emulation is broken, although for instructions |
/branches/sparc/kernel/arch/ia32/include/atomic.h |
---|
113,7 → 113,7 |
"xchgl %0, %1\n" |
"testl %1, %1\n" |
"jnz 0b\n" |
: "+m" (val->count), "=&r"(tmp) |
: "+m" (val->count), "=r"(tmp) |
); |
/* |
* Prevent critical section code from bleeding out this way up. |
/branches/sparc/kernel/arch/ia32/Makefile.inc |
---|
29,15 → 29,11 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_NAME = elf32-i386 |
BFD_ARCH = i386 |
BFD = binary |
TARGET = i686-pc-linux-gnu |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/i686 |
TOOLCHAIN_DIR = /usr/local/i686 |
DEFS += -DMACHINE=$(MACHINE) -D__32_BITS__ |
/branches/sparc/kernel/arch/ppc32/Makefile.inc |
---|
29,15 → 29,11 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_NAME = elf32-powerpc |
BFD_ARCH = powerpc:common |
BFD = binary |
TARGET = ppc-linux-gnu |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ppc |
TOOLCHAIN_DIR = /usr/local/ppc |
GCC_CFLAGS += -mcpu=powerpc -msoft-float -m32 |
AFLAGS += -a32 |
/branches/sparc/kernel/arch/ppc64/Makefile.inc |
---|
29,15 → 29,11 |
## Toolchain configuration |
# |
ifndef CROSS_PREFIX |
CROSS_PREFIX = /usr/local |
endif |
BFD_NAME = elf64-powerpc |
BFD_ARCH = powerpc:common64 |
BFD = binary |
TARGET = ppc64-linux-gnu |
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ppc64 |
TOOLCHAIN_DIR = /usr/local/ppc64 |
GCC_CFLAGS += -mcpu=powerpc64 -msoft-float -m64 |
AFLAGS += -a64 |