/branches/tracing/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/tracing/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/tracing/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) |
#define DR6_BT (1<<15) |
#define DR6_BS (1<<14) |
#define DR6_BD (1<<13) |
/branches/tracing/kernel/arch/ia32/Makefile.inc |
---|
160,10 → 160,10 |
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 |
ifeq ($(CONFIG_UDEBUG),y) |
ARCH_SOURCES += \ |
arch/$(ARCH)/src/breakpoint.c |
endif |
/branches/tracing/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/tracing/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/tracing/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/tracing/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 */ |