1370ab57dSAlex Smith /* 2370ab57dSAlex Smith * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de. 3370ab57dSAlex Smith * Copyright 2007, Travis Geiselbrecht. All rights reserved. 4370ab57dSAlex Smith * Distributed under the terms of the MIT License. 5370ab57dSAlex Smith */ 6370ab57dSAlex Smith 7370ab57dSAlex Smith 8370ab57dSAlex Smith #include "x86_syscalls.h" 9370ab57dSAlex Smith 10370ab57dSAlex Smith #include <string.h> 11370ab57dSAlex Smith 12370ab57dSAlex Smith #include <KernelExport.h> 13370ab57dSAlex Smith 14370ab57dSAlex Smith #include <commpage.h> 15370ab57dSAlex Smith #include <cpu.h> 16370ab57dSAlex Smith #include <elf.h> 17370ab57dSAlex Smith #include <smp.h> 18370ab57dSAlex Smith 19370ab57dSAlex Smith 20370ab57dSAlex Smith // user syscall assembly stubs 2102dd3236SAlex Smith extern "C" void x86_user_syscall_int(void); 2202dd3236SAlex Smith extern unsigned int x86_user_syscall_int_end; 2302dd3236SAlex Smith extern "C" void x86_user_syscall_sysenter(void); 2402dd3236SAlex Smith extern unsigned int x86_user_syscall_sysenter_end; 25370ab57dSAlex Smith 26370ab57dSAlex Smith // sysenter handler 27370ab57dSAlex Smith extern "C" void x86_sysenter(); 28370ab57dSAlex Smith 29370ab57dSAlex Smith 30370ab57dSAlex Smith void (*gX86SetSyscallStack)(addr_t stackTop) = NULL; 31370ab57dSAlex Smith 32370ab57dSAlex Smith 33*f2f91078SPaweł Dziepak extern int memcpy_end; 34*f2f91078SPaweł Dziepak extern int memset_end; 35*f2f91078SPaweł Dziepak 36*f2f91078SPaweł Dziepak 37370ab57dSAlex Smith static bool 38370ab57dSAlex Smith all_cpus_have_feature(enum x86_feature_type type, int feature) 39370ab57dSAlex Smith { 40370ab57dSAlex Smith int i; 41370ab57dSAlex Smith int cpuCount = smp_get_num_cpus(); 42370ab57dSAlex Smith 43370ab57dSAlex Smith for (i = 0; i < cpuCount; i++) { 44370ab57dSAlex Smith if (!(gCPU[i].arch.feature[type] & feature)) 45370ab57dSAlex Smith return false; 46370ab57dSAlex Smith } 47370ab57dSAlex Smith 48370ab57dSAlex Smith return true; 49370ab57dSAlex Smith } 50370ab57dSAlex Smith 51370ab57dSAlex Smith 52370ab57dSAlex Smith static void 53370ab57dSAlex Smith set_intel_syscall_stack(addr_t stackTop) 54370ab57dSAlex Smith { 55370ab57dSAlex Smith x86_write_msr(IA32_MSR_SYSENTER_ESP, stackTop); 56370ab57dSAlex Smith } 57370ab57dSAlex Smith 58370ab57dSAlex Smith 59370ab57dSAlex Smith static void 60370ab57dSAlex Smith init_intel_syscall_registers(void* dummy, int cpuNum) 61370ab57dSAlex Smith { 62611376feSPawel Dziepak x86_write_msr(IA32_MSR_SYSENTER_CS, KERNEL_CODE_SELECTOR); 63370ab57dSAlex Smith x86_write_msr(IA32_MSR_SYSENTER_ESP, 0); 64370ab57dSAlex Smith x86_write_msr(IA32_MSR_SYSENTER_EIP, (addr_t)x86_sysenter); 65370ab57dSAlex Smith 66370ab57dSAlex Smith gX86SetSyscallStack = &set_intel_syscall_stack; 67370ab57dSAlex Smith } 68370ab57dSAlex Smith 69370ab57dSAlex Smith 70370ab57dSAlex Smith #if 0 71370ab57dSAlex Smith static void 72370ab57dSAlex Smith init_amd_syscall_registers(void* dummy, int cpuNum) 73370ab57dSAlex Smith { 74370ab57dSAlex Smith // TODO: ... 75370ab57dSAlex Smith } 76370ab57dSAlex Smith #endif 77370ab57dSAlex Smith 78370ab57dSAlex Smith 79370ab57dSAlex Smith // #pragma mark - 80370ab57dSAlex Smith 81370ab57dSAlex Smith 82370ab57dSAlex Smith void 83370ab57dSAlex Smith x86_initialize_syscall(void) 84370ab57dSAlex Smith { 8502dd3236SAlex Smith void* syscallCode = (void *)&x86_user_syscall_int; 8602dd3236SAlex Smith void* syscallCodeEnd = &x86_user_syscall_int_end; 87370ab57dSAlex Smith 88370ab57dSAlex Smith // check syscall 89370ab57dSAlex Smith if (all_cpus_have_feature(FEATURE_COMMON, IA32_FEATURE_SEP) 90370ab57dSAlex Smith && !(gCPU[0].arch.family == 6 && gCPU[0].arch.model < 3 91370ab57dSAlex Smith && gCPU[0].arch.stepping < 3)) { 92370ab57dSAlex Smith // Intel sysenter/sysexit 93370ab57dSAlex Smith dprintf("initialize_commpage_syscall(): sysenter/sysexit supported\n"); 94370ab57dSAlex Smith 95370ab57dSAlex Smith // the code to be used in userland 9602dd3236SAlex Smith syscallCode = (void *)&x86_user_syscall_sysenter; 9702dd3236SAlex Smith syscallCodeEnd = &x86_user_syscall_sysenter_end; 98370ab57dSAlex Smith 99370ab57dSAlex Smith // tell all CPUs to init their sysenter/sysexit related registers 100370ab57dSAlex Smith call_all_cpus_sync(&init_intel_syscall_registers, NULL); 101370ab57dSAlex Smith } else if (all_cpus_have_feature(FEATURE_EXT_AMD, 102370ab57dSAlex Smith IA32_FEATURE_AMD_EXT_SYSCALL)) { 103370ab57dSAlex Smith // AMD syscall/sysret 104370ab57dSAlex Smith dprintf("initialize_commpage_syscall(): syscall/sysret supported " 105370ab57dSAlex Smith "-- not yet by Haiku, though"); 106370ab57dSAlex Smith } else { 107370ab57dSAlex Smith // no special syscall support 108370ab57dSAlex Smith dprintf("initialize_commpage_syscall(): no special syscall support\n"); 109370ab57dSAlex Smith } 110370ab57dSAlex Smith 111370ab57dSAlex Smith // fill in the table entry 112370ab57dSAlex Smith size_t len = (size_t)((addr_t)syscallCodeEnd - (addr_t)syscallCode); 113e85e399fSPawel Dziepak addr_t position = fill_commpage_entry(COMMPAGE_ENTRY_X86_SYSCALL, 114e85e399fSPawel Dziepak syscallCode, len); 115370ab57dSAlex Smith 116*f2f91078SPaweł Dziepak // put the optimized functions into the commpage 117*f2f91078SPaweł Dziepak size_t memcpyLen = (addr_t)&memcpy_end - (addr_t)memcpy; 118*f2f91078SPaweł Dziepak addr_t memcpyPosition = fill_commpage_entry(COMMPAGE_ENTRY_X86_MEMCPY, 119*f2f91078SPaweł Dziepak (const void*)memcpy, memcpyLen); 120*f2f91078SPaweł Dziepak size_t memsetLen = (addr_t)&memset_end - (addr_t)memset; 121*f2f91078SPaweł Dziepak addr_t memsetPosition = fill_commpage_entry(COMMPAGE_ENTRY_X86_MEMSET, 122*f2f91078SPaweł Dziepak (const void*)memset, memsetLen); 123*f2f91078SPaweł Dziepak 124370ab57dSAlex Smith // add syscall to the commpage image 125370ab57dSAlex Smith image_id image = get_commpage_image(); 126*f2f91078SPaweł Dziepak elf_add_memory_image_symbol(image, "commpage_memcpy", memcpyPosition, 127*f2f91078SPaweł Dziepak memcpyLen, B_SYMBOL_TYPE_TEXT); 128*f2f91078SPaweł Dziepak elf_add_memory_image_symbol(image, "commpage_memset", memsetPosition, 129*f2f91078SPaweł Dziepak memsetLen, B_SYMBOL_TYPE_TEXT); 130e85e399fSPawel Dziepak elf_add_memory_image_symbol(image, "commpage_syscall", position, len, 131370ab57dSAlex Smith B_SYMBOL_TYPE_TEXT); 132370ab57dSAlex Smith } 133