2 * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2007, Travis Geiselbrecht. All rights reserved.
4 * Distributed under the terms of the MIT License.
8 #include "x86_syscalls.h"
12 #include <KernelExport.h>
20 // user syscall assembly stubs
21 extern "C" void x86_user_syscall_int(void);
22 extern unsigned int x86_user_syscall_int_end
;
23 extern "C" void x86_user_syscall_sysenter(void);
24 extern unsigned int x86_user_syscall_sysenter_end
;
27 extern "C" void x86_sysenter();
30 void (*gX86SetSyscallStack
)(addr_t stackTop
) = NULL
;
33 extern int memcpy_end
;
34 extern int memset_end
;
38 all_cpus_have_feature(enum x86_feature_type type
, int feature
)
41 int cpuCount
= smp_get_num_cpus();
43 for (i
= 0; i
< cpuCount
; i
++) {
44 if (!(gCPU
[i
].arch
.feature
[type
] & feature
))
53 set_intel_syscall_stack(addr_t stackTop
)
55 x86_write_msr(IA32_MSR_SYSENTER_ESP
, stackTop
);
60 init_intel_syscall_registers(void* dummy
, int cpuNum
)
62 x86_write_msr(IA32_MSR_SYSENTER_CS
, KERNEL_CODE_SELECTOR
);
63 x86_write_msr(IA32_MSR_SYSENTER_ESP
, 0);
64 x86_write_msr(IA32_MSR_SYSENTER_EIP
, (addr_t
)x86_sysenter
);
66 gX86SetSyscallStack
= &set_intel_syscall_stack
;
72 init_amd_syscall_registers(void* dummy
, int cpuNum
)
83 x86_initialize_syscall(void)
85 void* syscallCode
= (void *)&x86_user_syscall_int
;
86 void* syscallCodeEnd
= &x86_user_syscall_int_end
;
89 if (all_cpus_have_feature(FEATURE_COMMON
, IA32_FEATURE_SEP
)
90 && !(gCPU
[0].arch
.family
== 6 && gCPU
[0].arch
.model
< 3
91 && gCPU
[0].arch
.stepping
< 3)) {
92 // Intel sysenter/sysexit
93 dprintf("initialize_commpage_syscall(): sysenter/sysexit supported\n");
95 // the code to be used in userland
96 syscallCode
= (void *)&x86_user_syscall_sysenter
;
97 syscallCodeEnd
= &x86_user_syscall_sysenter_end
;
99 // tell all CPUs to init their sysenter/sysexit related registers
100 call_all_cpus_sync(&init_intel_syscall_registers
, NULL
);
101 } else if (all_cpus_have_feature(FEATURE_EXT_AMD
,
102 IA32_FEATURE_AMD_EXT_SYSCALL
)) {
103 // AMD syscall/sysret
104 dprintf("initialize_commpage_syscall(): syscall/sysret supported "
105 "-- not yet by Haiku, though");
107 // no special syscall support
108 dprintf("initialize_commpage_syscall(): no special syscall support\n");
111 // fill in the table entry
112 size_t len
= (size_t)((addr_t
)syscallCodeEnd
- (addr_t
)syscallCode
);
113 addr_t position
= fill_commpage_entry(COMMPAGE_ENTRY_X86_SYSCALL
,
116 // put the optimized functions into the commpage
117 size_t memcpyLen
= (addr_t
)&memcpy_end
- (addr_t
)memcpy
;
118 addr_t memcpyPosition
= fill_commpage_entry(COMMPAGE_ENTRY_X86_MEMCPY
,
119 (const void*)memcpy
, memcpyLen
);
120 size_t memsetLen
= (addr_t
)&memset_end
- (addr_t
)memset
;
121 addr_t memsetPosition
= fill_commpage_entry(COMMPAGE_ENTRY_X86_MEMSET
,
122 (const void*)memset
, memsetLen
);
124 // add syscall to the commpage image
125 image_id image
= get_commpage_image();
126 elf_add_memory_image_symbol(image
, "commpage_memcpy", memcpyPosition
,
127 memcpyLen
, B_SYMBOL_TYPE_TEXT
);
128 elf_add_memory_image_symbol(image
, "commpage_memset", memsetPosition
,
129 memsetLen
, B_SYMBOL_TYPE_TEXT
);
130 elf_add_memory_image_symbol(image
, "commpage_syscall", position
, len
,