* Moved the syscall stuff from arch_commpage.cpp to x86_syscalls.{cpp,h}.

* On context switches we do now set the IA32_MSR_SYSENTER_ESP. This saves us
  setting esp at the beginning of x86_sysenter(). More importantly when
  entering it in single-step mode, this no longer causes a double fault
  (cf. #3487). We still don't handle the resulting debug exception correctly,
  so that we still get a (continuable) panic().


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35609 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2010-02-24 19:50:20 +00:00
parent 464d9f1252
commit 2cf60f9070
6 changed files with 151 additions and 96 deletions
+1
View File
@@ -36,6 +36,7 @@ KernelMergeObject kernel_arch_x86.o :
vm86.cpp
x86_physical_page_mapper.cpp
x86_physical_page_mapper_large_memory.cpp
x86_syscalls.cpp
x86_apic.cpp
x86_hpet.cpp
+2 -94
View File
@@ -7,99 +7,7 @@
#include <commpage.h>
#include <string.h>
#include <KernelExport.h>
#include <cpu.h>
#include <elf.h>
#include <smp.h>
// user syscall assembly stubs
extern "C" void _user_syscall_int(void);
extern unsigned int _user_syscall_int_end;
extern "C" void _user_syscall_sysenter(void);
extern unsigned int _user_syscall_sysenter_end;
// sysenter handler
extern "C" void x86_sysenter();
static bool
all_cpus_have_feature(enum x86_feature_type type, int feature)
{
int i;
int cpuCount = smp_get_num_cpus();
for (i = 0; i < cpuCount; i++) {
if (!(gCPU[i].arch.feature[type] & feature))
return false;
}
return true;
}
static void
init_intel_syscall_registers(void* dummy, int cpuNum)
{
x86_write_msr(IA32_MSR_SYSENTER_CS, KERNEL_CODE_SEG);
x86_write_msr(IA32_MSR_SYSENTER_ESP, 0);
x86_write_msr(IA32_MSR_SYSENTER_EIP, (addr_t)x86_sysenter);
}
#if 0
static void
init_amd_syscall_registers(void* dummy, int cpuNum)
{
// TODO: ...
}
#endif
static status_t
initialize_commpage_syscall(void)
{
void* syscallCode = (void *)&_user_syscall_int;
void* syscallCodeEnd = &_user_syscall_int_end;
// check syscall
if (all_cpus_have_feature(FEATURE_COMMON, IA32_FEATURE_SEP)
&& !(gCPU[0].arch.family == 6 && gCPU[0].arch.model < 3
&& gCPU[0].arch.stepping < 3)) {
// Intel sysenter/sysexit
dprintf("initialize_commpage_syscall(): sysenter/sysexit supported\n");
// the code to be used in userland
syscallCode = (void *)&_user_syscall_sysenter;
syscallCodeEnd = &_user_syscall_sysenter_end;
// tell all CPUs to init their sysenter/sysexit related registers
call_all_cpus_sync(&init_intel_syscall_registers, NULL);
} else if (all_cpus_have_feature(FEATURE_EXT_AMD,
IA32_FEATURE_AMD_EXT_SYSCALL)) {
// AMD syscall/sysret
dprintf("initialize_commpage_syscall(): syscall/sysret supported "
"-- not yet by Haiku, though");
} else {
// no special syscall support
dprintf("initialize_commpage_syscall(): no special syscall support\n");
}
// fill in the table entry
size_t len = (size_t)((addr_t)syscallCodeEnd - (addr_t)syscallCode);
fill_commpage_entry(COMMPAGE_ENTRY_X86_SYSCALL, syscallCode, len);
// add syscall to the commpage image
image_id image = get_commpage_image();
elf_add_memory_image_symbol(image, "commpage_syscall",
((addr_t*)USER_COMMPAGE_ADDR)[COMMPAGE_ENTRY_X86_SYSCALL], len,
B_SYMBOL_TYPE_TEXT);
return B_OK;
}
#include "x86_syscalls.h"
status_t
@@ -113,7 +21,7 @@ status_t
arch_commpage_init_post_cpus(void)
{
// select the optimum syscall mechanism and patch the commpage
initialize_commpage_syscall();
x86_initialize_commpage_syscall();
return B_OK;
}
+1 -2
View File
@@ -555,9 +555,8 @@ FUNCTION_END(handle_syscall)
ecx - user esp
*/
FUNCTION(x86_sysenter):
// switch the stack
// get the thread
movl %dr3, %edx
movl THREAD_kernel_stack_top(%edx), %esp
// push the iframe
pushl $USER_DATA_SEG // user_ss
@@ -26,6 +26,7 @@
#include <vm/VMAddressSpace.h>
#include "x86_paging.h"
#include "x86_syscalls.h"
#include "X86VMTranslationMap.h"
@@ -357,6 +358,7 @@ void
arch_thread_context_switch(struct thread *from, struct thread *to)
{
i386_set_tss_and_kstack(to->kernel_stack_top);
x86_set_syscall_stack(to->kernel_stack_top);
// set TLS GDT entry to the current thread - since this action is
// dependent on the current CPU, we have to do it here
@@ -451,6 +453,7 @@ arch_thread_enter_userspace(struct thread *t, addr_t entry, void *args1,
// set the CPU dependent GDT entry for TLS
set_tls_context(t);
x86_set_syscall_stack(t->kernel_stack_top);
x86_enter_userspace(entry, stackTop);
return B_OK;
+118
View File
@@ -0,0 +1,118 @@
/*
* Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2007, Travis Geiselbrecht. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "x86_syscalls.h"
#include <string.h>
#include <KernelExport.h>
#include <commpage.h>
#include <cpu.h>
#include <elf.h>
#include <smp.h>
// user syscall assembly stubs
extern "C" void _user_syscall_int(void);
extern unsigned int _user_syscall_int_end;
extern "C" void _user_syscall_sysenter(void);
extern unsigned int _user_syscall_sysenter_end;
// sysenter handler
extern "C" void x86_sysenter();
void (*gX86SetSyscallStack)(addr_t stackTop) = NULL;
static bool
all_cpus_have_feature(enum x86_feature_type type, int feature)
{
int i;
int cpuCount = smp_get_num_cpus();
for (i = 0; i < cpuCount; i++) {
if (!(gCPU[i].arch.feature[type] & feature))
return false;
}
return true;
}
static void
set_intel_syscall_stack(addr_t stackTop)
{
x86_write_msr(IA32_MSR_SYSENTER_ESP, stackTop);
}
static void
init_intel_syscall_registers(void* dummy, int cpuNum)
{
x86_write_msr(IA32_MSR_SYSENTER_CS, KERNEL_CODE_SEG);
x86_write_msr(IA32_MSR_SYSENTER_ESP, 0);
x86_write_msr(IA32_MSR_SYSENTER_EIP, (addr_t)x86_sysenter);
gX86SetSyscallStack = &set_intel_syscall_stack;
}
#if 0
static void
init_amd_syscall_registers(void* dummy, int cpuNum)
{
// TODO: ...
}
#endif
// #pragma mark -
status_t
x86_initialize_commpage_syscall(void)
{
void* syscallCode = (void *)&_user_syscall_int;
void* syscallCodeEnd = &_user_syscall_int_end;
// check syscall
if (all_cpus_have_feature(FEATURE_COMMON, IA32_FEATURE_SEP)
&& !(gCPU[0].arch.family == 6 && gCPU[0].arch.model < 3
&& gCPU[0].arch.stepping < 3)) {
// Intel sysenter/sysexit
dprintf("initialize_commpage_syscall(): sysenter/sysexit supported\n");
// the code to be used in userland
syscallCode = (void *)&_user_syscall_sysenter;
syscallCodeEnd = &_user_syscall_sysenter_end;
// tell all CPUs to init their sysenter/sysexit related registers
call_all_cpus_sync(&init_intel_syscall_registers, NULL);
} else if (all_cpus_have_feature(FEATURE_EXT_AMD,
IA32_FEATURE_AMD_EXT_SYSCALL)) {
// AMD syscall/sysret
dprintf("initialize_commpage_syscall(): syscall/sysret supported "
"-- not yet by Haiku, though");
} else {
// no special syscall support
dprintf("initialize_commpage_syscall(): no special syscall support\n");
}
// fill in the table entry
size_t len = (size_t)((addr_t)syscallCodeEnd - (addr_t)syscallCode);
fill_commpage_entry(COMMPAGE_ENTRY_X86_SYSCALL, syscallCode, len);
// add syscall to the commpage image
image_id image = get_commpage_image();
elf_add_memory_image_symbol(image, "commpage_syscall",
((addr_t*)USER_COMMPAGE_ADDR)[COMMPAGE_ENTRY_X86_SYSCALL], len,
B_SYMBOL_TYPE_TEXT);
return B_OK;
}
+26
View File
@@ -0,0 +1,26 @@
/*
* Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef _KERNEL_ARCH_X86_SYSCALLS_H
#define _KERNEL_ARCH_X86_SYSCALLS_H
#include <SupportDefs.h>
extern void (*gX86SetSyscallStack)(addr_t stackTop);
status_t x86_initialize_commpage_syscall();
static inline void
x86_set_syscall_stack(addr_t stackTop)
{
if (gX86SetSyscallStack != NULL)
gX86SetSyscallStack(stackTop);
}
#endif // _KERNEL_ARCH_X86_SYSCALLS_H