Subversion Repositories HelenOS

Compare Revisions

No changes between revisions

Ignore whitespace Rev 3534 → Rev 3535

/branches/dynload/kernel/generic/include/stdarg.h
45,7 → 45,7
#define va_start(ap, last) __builtin_va_start(ap, last)
#define va_arg(ap, type) __builtin_va_arg(ap, type)
#define va_end(ap) __builtin_va_end(ap)
#define va_copy(dst,src) __builtin_va_copy(dst,src)
#define va_copy(dst, src) __builtin_va_copy(dst, src)
 
#endif
 
/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 */
63,6 → 64,17
* wake up and terminate.
*/
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");
79,13 → 91,75
spinlock_unlock(&TASK->kernel_box.lock);
}
 
/** 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)
{
ipl_t ipl;
 
LOG("kbox_proc_phone_hungup()\n");
 
/* Was it our debugger, who hung up? */
if (call->sender == TASK->udebug.debugger) {
/* Terminate debugging session (if any) */
LOG("kbox: terminate debug session\n");
ipl = interrupts_disable();
spinlock_lock(&TASK->lock);
udebug_task_cleanup(TASK);
spinlock_unlock(&TASK->lock);
interrupts_restore(ipl);
} else {
LOG("kbox: was not debugger\n");
}
 
LOG("kbox: continue with hangup message\n");
IPC_SET_RETVAL(call->data, 0);
ipc_answer(&TASK->kernel_box, call);
 
ipl = interrupts_disable();
spinlock_lock(&TASK->lock);
spinlock_lock(&TASK->answerbox.lock);
if (list_empty(&TASK->answerbox.connected_phones)) {
/*
* 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;
}
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;
int method;
bool done;
ipl_t ipl;
 
(void)arg;
LOG("kbox_thread_proc()\n");
95,46 → 169,28
call = ipc_wait_for_call(&TASK->kernel_box, SYNCH_NO_TIMEOUT,
SYNCH_FLAGS_NONE);
 
if (call != NULL) {
method = IPC_GET_METHOD(call->data);
if (call == NULL)
continue; /* Try again. */
 
if (method == IPC_M_DEBUG_ALL) {
udebug_call_receive(call);
}
switch (IPC_GET_METHOD(call->data)) {
 
if (method == IPC_M_PHONE_HUNGUP) {
LOG("kbox: handle hangup message\n");
case IPC_M_DEBUG_ALL:
/* Handle debug call. */
udebug_call_receive(call);
break;
 
/* Was it our debugger, who hung up? */
if (call->sender == TASK->udebug.debugger) {
/* Terminate debugging session (if any) */
LOG("kbox: terminate debug session\n");
ipl = interrupts_disable();
spinlock_lock(&TASK->lock);
udebug_task_cleanup(TASK);
spinlock_unlock(&TASK->lock);
interrupts_restore(ipl);
} else {
LOG("kbox: was not debugger\n");
}
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;
 
LOG("kbox: continue with hangup message\n");
IPC_SET_RETVAL(call->data, 0);
ipc_answer(&TASK->kernel_box, call);
 
ipl = interrupts_disable();
spinlock_lock(&TASK->lock);
spinlock_lock(&TASK->answerbox.lock);
if (list_empty(&TASK->answerbox.connected_phones)) {
/* Last phone has been disconnected */
TASK->kb_thread = NULL;
done = true;
LOG("phone list is empty\n");
}
spinlock_unlock(&TASK->answerbox.lock);
spinlock_unlock(&TASK->lock);
interrupts_restore(ipl);
}
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 */