Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2604 → Rev 2606

/trunk/kernel/arch/amd64/include/proc/thread.h
35,8 → 35,14
#ifndef KERN_amd64_THREAD_H_
#define KERN_amd64_THREAD_H_
 
/* CAUTION: keep these in sync with low level assembly code in syscall_entry */
#define SYSCALL_USTACK_RSP 0
#define SYSCALL_KSTACK_RSP 1
 
typedef struct {
unative_t tls;
/** User and kernel RSP for syscalls. */
uint64_t syscall_rsp[2];
} thread_arch_t;
 
#define thr_constructor_arch(t)
/trunk/kernel/arch/amd64/src/syscall.c
52,13 → 52,13
 
/* Setup syscall entry address */
/* This is _mess_ - the 64-bit CS is argument+16,
* the SS is argument+8. The order is:
/* This is _mess_ - the 64-bit CS is argument + 16,
* the SS is argument + 8. The order is:
* +0(KDATA_DES), +8(UDATA_DES), +16(UTEXT_DES)
*/
write_msr(AMD_MSR_STAR,
((uint64_t)(gdtselector(KDATA_DES) | PL_USER)<<48) \
| ((uint64_t)(gdtselector(KTEXT_DES) | PL_KERNEL)<<32));
((uint64_t)(gdtselector(KDATA_DES) | PL_USER) << 48) |
((uint64_t)(gdtselector(KTEXT_DES) | PL_KERNEL) << 32));
write_msr(AMD_MSR_LSTAR, (uint64_t)syscall_entry);
/* Mask RFLAGS on syscall
* - disable interrupts, until we exchange the stack register
/trunk/kernel/arch/amd64/src/asm_utils.S
220,10 → 220,11
.macro handler i n
 
/*
* Choose between version with error code and version without error code.
* Both versions have to be of the same size. amd64 assembly is, however,
* a little bit tricky. For instance, subq $0x80, %rsp and subq $0x78, %rsp
* can result in two instructions with different op-code lengths.
* Choose between version with error code and version without error
* code. Both versions have to be of the same size. amd64 assembly is,
* however, a little bit tricky. For instance, subq $0x80, %rsp and
* subq $0x78, %rsp can result in two instructions with different
* op-code lengths.
* Therefore we align the interrupt handlers.
*/
 
269,34 → 270,53
handler 0 IDT_ITEMS
h_end:
 
## Low-level syscall handler
#
# Registers on entry:
#
# @param rcx Userspace return address.
# @param r11 Userspace RLFAGS.
#
# @param rax Syscall number.
# @param rdi 1st syscall argument.
# @param rsi 2nd syscall argument.
# @param rdx 3rd syscall argument.
# @param r10 4th syscall argument. Used instead of RCX because the
# SYSCALL instruction clobbers it.
# @param r8 5th syscall argument.
# @param r9 6th syscall argument.
#
# @return Return value is in rax.
#
syscall_entry:
# Switch to hidden gs
swapgs
# %gs:0 now points to pointer to stack page
mov %gs:0, %r10 # We have a ptr to stack page in r10
addq $PAGE_SIZE-16, %r10 # We need some space to store old %sp
swapgs # Switch to hidden gs
#
# %gs:0 Scratch space for this thread's user RSP
# %gs:8 Address to be used as this thread's kernel RSP
#
movq %rsp, %gs:0 # Save this thread's user RSP
movq %gs:8, %rsp # Set this thread's kernel RSP
swapgs # Switch back to remain consistent
sti
movq %rsp, 0(%r10) # Save old stack pointer to stack
movq %r10, %rsp # Change to new stack
pushq %rcx # Return address
pushq %r11 # Save flags
pushq %rcx
pushq %r11
 
# Switch back to remain consistent
swapgs
 
sti
movq %r9, %rcx # Exchange last parameter as a third
movq %r10, %rcx # Copy the 4th argument where it is expected
pushq %rax
call syscall_handler
cli # We will be touching stack pointer
addq $8, %rsp
popq %r11
popq %rcx
movq 0(%rsp), %rsp
 
cli
swapgs
movq %gs:0, %rsp # Restore the user RSP
swapgs
 
sysretq
 
.data
.global interrupt_handler_size
 
/trunk/kernel/arch/amd64/src/proc/scheduler.c
56,12 → 56,14
/** Perform amd64 specific tasks needed before the new thread is scheduled. */
void before_thread_runs_arch(void)
{
CPU->arch.tss->rsp0 = (uintptr_t) &THREAD->kstack[THREAD_STACK_SIZE-SP_DELTA];
CPU->arch.tss->rsp0 =
(uintptr_t) &THREAD->kstack[THREAD_STACK_SIZE - SP_DELTA];
 
/* Syscall support - write address of thread stack pointer to
* hidden part of gs */
/*
* Syscall support.
*/
swapgs();
write_msr(AMD_MSR_GS, (uint64_t)&THREAD->kstack);
write_msr(AMD_MSR_GS, (uintptr_t)THREAD->arch.syscall_rsp);
swapgs();
 
/* TLS support - set FS to thread local storage */
71,8 → 73,7
/* Set watchpoint on AS to ensure that nobody sets it to zero */
if (CPU->id < BKPOINTS_MAX)
breakpoint_add(&((the_t *) THREAD->kstack)->as,
BKPOINT_WRITE | BKPOINT_CHECK_ZERO,
CPU->id);
BKPOINT_WRITE | BKPOINT_CHECK_ZERO, CPU->id);
#endif
}
 
/trunk/kernel/arch/amd64/src/proc/thread.c
41,6 → 41,12
void thread_create_arch(thread_t *t)
{
t->arch.tls = 0;
t->arch.syscall_rsp[SYSCALL_USTACK_RSP] = 0;
/*
* Kernel RSP can be precalculated at thread creation time.
*/
t->arch.syscall_rsp[SYSCALL_KSTACK_RSP] =
(uintptr_t)&t->kstack[PAGE_SIZE - sizeof(uint64_t)];
}
 
/** @}