/branches/dynload/kernel/generic/src/ipc/kbox.c |
---|
45,6 → 45,7 |
void ipc_kbox_cleanup(void) |
{ |
ipl_t ipl; |
bool have_kb_thread; |
/* Only hold kb_cleanup_lock while setting kb_finished - this is enough */ |
64,6 → 65,17 |
*/ |
ipc_answerbox_slam_phones(&TASK->kernel_box, have_kb_thread); |
/* |
* If the task was being debugged, clean up debugging session. |
* This is necessarry as slamming the phones won't force |
* kbox thread to clean it up since sender != debugger. |
*/ |
ipl = interrupts_disable(); |
spinlock_lock(&TASK->lock); |
udebug_task_cleanup(TASK); |
spinlock_unlock(&TASK->lock); |
interrupts_restore(ipl); |
if (have_kb_thread) { |
LOG("join kb_thread..\n"); |
thread_join(TASK->kb_thread); |
79,32 → 91,18 |
spinlock_unlock(&TASK->kernel_box.lock); |
} |
static void kbox_thread_proc(void *arg) |
/** Handle hangup message in kbox. |
* |
* @param call The IPC_M_PHONE_HUNGUP call structure. |
* @param last Output, the function stores @c true here if |
* this was the last phone, @c false otherwise. |
**/ |
static void kbox_proc_phone_hungup(call_t *call, bool *last) |
{ |
call_t *call; |
int method; |
bool done; |
ipl_t ipl; |
(void)arg; |
LOG("kbox_thread_proc()\n"); |
done = false; |
LOG("kbox_proc_phone_hungup()\n"); |
while (!done) { |
call = ipc_wait_for_call(&TASK->kernel_box, SYNCH_NO_TIMEOUT, |
SYNCH_FLAGS_NONE); |
if (call != NULL) { |
method = IPC_GET_METHOD(call->data); |
if (method == IPC_M_DEBUG_ALL) { |
udebug_call_receive(call); |
} |
if (method == IPC_M_PHONE_HUNGUP) { |
LOG("kbox: handle hangup message\n"); |
/* Was it our debugger, who hung up? */ |
if (call->sender == TASK->udebug.debugger) { |
/* Terminate debugging session (if any) */ |
126,15 → 124,73 |
spinlock_lock(&TASK->lock); |
spinlock_lock(&TASK->answerbox.lock); |
if (list_empty(&TASK->answerbox.connected_phones)) { |
/* Last phone has been disconnected */ |
/* |
* Last phone has been disconnected. Detach this thread so it |
* gets freed and signal to the caller. |
*/ |
/* Only detach kbox thread unless already terminating. */ |
mutex_lock(&TASK->kb_cleanup_lock); |
if (&TASK->kb_finished == false) { |
/* Detach kbox thread so it gets freed from memory. */ |
thread_detach(TASK->kb_thread); |
TASK->kb_thread = NULL; |
done = true; |
} |
mutex_unlock(&TASK->kb_cleanup_lock); |
LOG("phone list is empty\n"); |
*last = true; |
} else { |
*last = false; |
} |
spinlock_unlock(&TASK->answerbox.lock); |
spinlock_unlock(&TASK->lock); |
interrupts_restore(ipl); |
} |
/** Implementing function for the kbox thread. |
* |
* This function listens for debug requests. It terminates |
* when all phones are disconnected from the kbox. |
* |
* @param arg Ignored. |
*/ |
static void kbox_thread_proc(void *arg) |
{ |
call_t *call; |
bool done; |
(void)arg; |
LOG("kbox_thread_proc()\n"); |
done = false; |
while (!done) { |
call = ipc_wait_for_call(&TASK->kernel_box, SYNCH_NO_TIMEOUT, |
SYNCH_FLAGS_NONE); |
if (call == NULL) |
continue; /* Try again. */ |
switch (IPC_GET_METHOD(call->data)) { |
case IPC_M_DEBUG_ALL: |
/* Handle debug call. */ |
udebug_call_receive(call); |
break; |
case IPC_M_PHONE_HUNGUP: |
/* |
* Process the hangup call. If this was the last |
* phone, done will be set to true and the |
* while loop will terminate. |
*/ |
kbox_proc_phone_hungup(call, &done); |
break; |
default: |
/* Ignore */ |
break; |
} |
} |
/branches/dynload/kernel/generic/src/ipc/sysipc.c |
---|
822,12 → 822,16 |
ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC)); |
if (!(call->flags & IPC_CALL_DISCARD_ANSWER)) |
atomic_dec(&TASK->active_calls); |
if (call->flags & IPC_CALL_DISCARD_ANSWER) { |
ipc_call_free(call); |
goto restart; |
} else { |
/* |
* Decrement the counter of active calls only if the |
* call is not an answer to IPC_M_PHONE_HUNGUP, |
* which doesn't contribute to the counter. |
*/ |
atomic_dec(&TASK->active_calls); |
} |
STRUCT_TO_USPACE(&calldata->args, &call->data.args); |
/branches/dynload/kernel/generic/src/ipc/ipc.c |
---|
508,7 → 508,8 |
interrupts_restore(ipl); |
/* Free unused call */ |
if (call) ipc_call_free(call); |
if (call) |
ipc_call_free(call); |
} |
/** Cleans up all IPC communication of the current task. |
573,6 → 574,11 |
(call->flags & IPC_CALL_NOTIF)); |
ASSERT(!(call->flags & IPC_CALL_STATIC_ALLOC)); |
/* |
* Record the receipt of this call in the current task's counter |
* of active calls. IPC_M_PHONE_HUNGUP calls do not contribute |
* to this counter so do not record answers to them either. |
*/ |
if (!(call->flags & IPC_CALL_DISCARD_ANSWER)) |
atomic_dec(&TASK->active_calls); |
ipc_call_free(call); |
/branches/dynload/kernel/Makefile |
---|
44,7 → 44,7 |
GCC_CFLAGS = -I$(INCLUDES) -O$(OPTIMIZATION) \ |
-fno-builtin -Wall -Wextra -Wno-unused-parameter -Wmissing-prototypes -Werror \ |
-nostdlib -nostdinc |
-nostdlib -nostdinc -pipe |
ICC_CFLAGS = -I$(INCLUDES) -O$(OPTIMIZATION) \ |
-fno-builtin -Wall -Wmissing-prototypes -Werror \ |
365,7 → 365,7 |
ln -sfn ../../genarch/include/ generic/include/genarch |
depend: archlinks |
-makedepend $(DEFS) $(CFLAGS) -f - $(ARCH_SOURCES) $(GENARCH_SOURCES) $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null |
-makedepend -f - -- $(DEFS) $(CFLAGS) -- $(ARCH_SOURCES) $(GENARCH_SOURCES) $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null |
arch/$(ARCH)/_link.ld: arch/$(ARCH)/_link.ld.in |
$(GCC) $(DEFS) $(GCC_CFLAGS) -D__ASM__ -D__LINKER__ -E -x c $< | grep -v "^\#" > $@ |
/branches/dynload/kernel/arch/sparc64/include/trap/regwin.h |
---|
39,6 → 39,7 |
#include <arch/stack.h> |
#include <arch/arch.h> |
#include <align.h> |
#define TT_CLEAN_WINDOW 0x24 |
#define TT_SPILL_0_NORMAL 0x80 /* kernel spills */ |
72,6 → 73,11 |
#define I6_OFFSET 112 |
#define I7_OFFSET 120 |
/* Uspace Window Buffer constants. */ |
#define UWB_SIZE ((NWINDOWS - 1) * STACK_WINDOW_SAVE_AREA_SIZE) |
#define UWB_ALIGNMENT 1024 |
#define UWB_ASIZE ALIGN_UP(UWB_SIZE, UWB_ALIGNMENT) |
#ifdef __ASM__ |
/* |
/branches/dynload/kernel/arch/sparc64/src/proc/thread.c |
---|
34,9 → 34,8 |
#include <proc/thread.h> |
#include <arch/proc/thread.h> |
#include <mm/frame.h> |
#include <mm/page.h> |
#include <arch/mm/page.h> |
#include <mm/slab.h> |
#include <arch/trap/regwin.h> |
#include <align.h> |
void thr_constructor_arch(thread_t *t) |
50,12 → 49,12 |
void thr_destructor_arch(thread_t *t) |
{ |
if (t->arch.uspace_window_buffer) { |
uintptr_t uw_buf = (uintptr_t) t->arch.uspace_window_buffer; |
/* |
* Mind the possible alignment of the userspace window buffer |
* belonging to a killed thread. |
*/ |
frame_free(KA2PA(ALIGN_DOWN((uintptr_t) |
t->arch.uspace_window_buffer, PAGE_SIZE))); |
free((uint8_t *) ALIGN_DOWN(uw_buf, UWB_ALIGNMENT)); |
} |
} |
67,7 → 66,7 |
* The thread needs userspace window buffer and the object |
* returned from the slab allocator doesn't have any. |
*/ |
t->arch.uspace_window_buffer = frame_alloc(ONE_FRAME, FRAME_KA); |
t->arch.uspace_window_buffer = malloc(UWB_ASIZE, 0); |
} else { |
uintptr_t uw_buf = (uintptr_t) t->arch.uspace_window_buffer; |
76,7 → 75,7 |
* belonging to a killed thread. |
*/ |
t->arch.uspace_window_buffer = (uint8_t *) ALIGN_DOWN(uw_buf, |
PAGE_SIZE); |
UWB_ASIZE); |
} |
} |
/branches/dynload/kernel/arch/sparc64/src/trap/trap_table.S |
---|
748,9 → 748,8 |
* Fill all windows stored in the buffer. |
*/ |
clr %g4 |
set PAGE_SIZE - 1, %g5 |
0: andcc %g7, %g5, %g0 ! PAGE_SIZE alignment check |
bz 0f ! %g7 is page-aligned, no more windows to refill |
0: andcc %g7, UWB_ALIGNMENT - 1, %g0 ! alignment check |
bz 0f ! %g7 is UWB_ALIGNMENT-aligned, no more windows to refill |
nop |
add %g7, -STACK_WINDOW_SAVE_AREA_SIZE, %g7 |
/branches/dynload/kernel/arch/ia64/include/asm.h |
---|
44,21 → 44,50 |
static inline void outb(uint64_t port,uint8_t v) |
{ |
*((char *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))) = v; |
*((uint8_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))) = v; |
asm volatile ("mf\n" ::: "memory"); |
} |
static inline void outw(uint64_t port,uint16_t v) |
{ |
*((uint16_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))) = v; |
asm volatile ("mf\n" ::: "memory"); |
} |
static inline void outl(uint64_t port,uint32_t v) |
{ |
*((uint32_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))) = v; |
asm volatile ("mf\n" ::: "memory"); |
} |
static inline uint8_t inb(uint64_t port) |
{ |
asm volatile ("mf\n" ::: "memory"); |
return *((char *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))); |
return *((uint8_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))); |
} |
static inline uint16_t inw(uint64_t port) |
{ |
asm volatile ("mf\n" ::: "memory"); |
return *((uint16_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xffE) | ( (port >> 2) << 12 )))); |
} |
static inline uint32_t inl(uint64_t port) |
{ |
asm volatile ("mf\n" ::: "memory"); |
return *((uint32_t *)(IA64_IOSPACE_ADDRESS + ( (port & 0xfff) | ( (port >> 2) << 12 )))); |
} |
/** Return base address of current stack |
* |
* Return the base address of the current stack. |
/branches/dynload/kernel/arch/amd64/include/syscall.h |
---|
35,8 → 35,6 |
#ifndef KERN_amd64_SYSCALL_H_ |
#define KERN_amd64_SYSCALL_H_ |
#include <arch/types.h> |
extern void syscall_setup_cpu(void); |
#endif |
/branches/dynload/kernel/arch/ia32/include/syscall.h |
---|
0,0 → 1,0 |
link ../../amd64/include/syscall.h |
Property changes: |
Added: svn:special |
+* |
\ No newline at end of property |
/branches/dynload/kernel/arch/ia32/include/asm.h |
---|
247,6 → 247,22 |
return v; |
} |
/** Write to MSR */ |
static inline void write_msr(uint32_t msr, uint64_t value) |
{ |
asm volatile ("wrmsr" : : "c" (msr), "a" ((uint32_t)(value)), |
"d" ((uint32_t)(value >> 32))); |
} |
static inline uint64_t read_msr(uint32_t msr) |
{ |
uint32_t ax, dx; |
asm volatile ("rdmsr" : "=a"(ax), "=d"(dx) : "c" (msr)); |
return ((uint64_t)dx << 32) | ax; |
} |
/** Return base address of current stack |
* |
* Return the base address of the current stack. |
/branches/dynload/kernel/arch/ia32/include/cpu.h |
---|
35,12 → 35,21 |
#ifndef KERN_ia32_CPU_H_ |
#define KERN_ia32_CPU_H_ |
#define EFLAGS_IF (1 << 9) |
#define EFLAGS_RF (1 << 16) |
#define CR4_OSFXSR_MASK (1<<9) |
/* Support for SYSENTER and SYSEXIT */ |
#define IA32_MSR_SYSENTER_CS 0x174 |
#define IA32_MSR_SYSENTER_ESP 0x175 |
#define IA32_MSR_SYSENTER_EIP 0x176 |
#ifndef __ASM__ |
#include <arch/pm.h> |
#include <arch/asm.h> |
#define EFLAGS_IF (1 << 9) |
#define EFLAGS_RF (1 << 16) |
typedef struct { |
int vendor; |
int family; |
51,9 → 60,8 |
count_t iomapver_copy; /** Copy of TASK's I/O Permission bitmap generation count. */ |
} cpu_arch_t; |
#endif |
#define CR4_OSFXSR_MASK (1<<9) |
#endif |
/** @} |
/branches/dynload/kernel/arch/ia32/Makefile.inc |
---|
160,4 → 160,5 |
arch/$(ARCH)/src/boot/boot.S \ |
arch/$(ARCH)/src/boot/memmap.c \ |
arch/$(ARCH)/src/fpu_context.c \ |
arch/$(ARCH)/src/debugger.c |
arch/$(ARCH)/src/debugger.c \ |
arch/$(ARCH)/src/syscall.c |
/branches/dynload/kernel/arch/ia32/src/asm.S |
---|
147,6 → 147,45 |
popfl |
.endm |
/* |
* The SYSENTER syscall mechanism can be used for syscalls with |
* four or fewer arguments. To pass these four arguments, we |
* use four registers: EDX, ECX, EBX, ESI. The syscall number |
* is passed in EAX. We use EDI to remember the return address |
* and EBP to remember the stack. The INT-based syscall mechanism |
* can actually handle six arguments plus the syscall number |
* entirely in registers. |
*/ |
.global sysenter_handler |
sysenter_handler: |
pushl %ebp # remember user stack |
pushl %edi # remember return user address |
pushl %gs # remember TLS |
pushl %eax # syscall number |
subl $8, %esp # unused sixth and fifth argument |
pushl %esi # fourth argument |
pushl %ebx # third argument |
pushl %ecx # second argument |
pushl %edx # first argument |
movw $16, %ax |
movw %ax, %ds |
movw %ax, %es |
cld |
call syscall_handler |
addl $28, %esp # remove arguments from stack |
pop %gs # restore TLS |
pop %edx # prepare return EIP for SYSEXIT |
pop %ecx # prepare userspace ESP for SYSEXIT |
sysexit # return to userspace |
## Declare interrupt handlers |
# |
# Declare interrupt handlers for n interrupt |
/branches/dynload/kernel/arch/ia32/src/cpu/cpu.c |
---|
42,6 → 42,7 |
#include <fpu_context.h> |
#include <arch/smp/apic.h> |
#include <arch/syscall.h> |
/* |
* Identification of CPUs. |
123,6 → 124,9 |
: "i" (CR4_OSFXSR_MASK|(1<<10)) |
); |
} |
/* Setup fast SYSENTER/SYSEXIT syscalls */ |
syscall_setup_cpu(); |
} |
void cpu_identify(void) |
/branches/dynload/kernel/arch/ia32/src/syscall.c |
---|
0,0 → 1,53 |
/* |
* Copyright (c) 2008 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. |
*/ |
/** @addtogroup ia32 |
* @{ |
*/ |
/** @file |
*/ |
#include <arch/syscall.h> |
#include <arch/cpu.h> |
#include <arch/asm.h> |
#include <arch/types.h> |
#include <arch/pm.h> |
/** Enable & setup support for SYSENTER/SYSEXIT */ |
void syscall_setup_cpu(void) |
{ |
extern void sysenter_handler(void); |
/* set kernel mode CS selector */ |
write_msr(IA32_MSR_SYSENTER_CS, selector(KTEXT_DES)); |
/* set kernel mode entry point */ |
write_msr(IA32_MSR_SYSENTER_EIP, (uint32_t) sysenter_handler); |
} |
/** @} |
*/ |
/branches/dynload/kernel/arch/ia32/src/proc/scheduler.c |
---|
58,8 → 58,14 |
*/ |
void before_thread_runs_arch(void) |
{ |
CPU->arch.tss->esp0 = (uintptr_t) &THREAD->kstack[THREAD_STACK_SIZE - |
uintptr_t kstk = (uintptr_t) &THREAD->kstack[THREAD_STACK_SIZE - |
SP_DELTA]; |
/* Set kernel stack for CP3 -> CPL0 switch via SYSENTER */ |
write_msr(IA32_MSR_SYSENTER_ESP, kstk); |
/* Set kernel stack for CPL3 -> CPL0 switch via interrupt */ |
CPU->arch.tss->esp0 = kstk; |
CPU->arch.tss->ss0 = selector(KDATA_DES); |
/* Set up TLS in GS register */ |