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 21*02dd3236SAlex Smith extern "C" void x86_user_syscall_int(void); 22*02dd3236SAlex Smith extern unsigned int x86_user_syscall_int_end; 23*02dd3236SAlex Smith extern "C" void x86_user_syscall_sysenter(void); 24*02dd3236SAlex 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 33370ab57dSAlex Smith static bool 34370ab57dSAlex Smith all_cpus_have_feature(enum x86_feature_type type, int feature) 35370ab57dSAlex Smith { 36370ab57dSAlex Smith int i; 37370ab57dSAlex Smith int cpuCount = smp_get_num_cpus(); 38370ab57dSAlex Smith 39370ab57dSAlex Smith for (i = 0; i < cpuCount; i++) { 40370ab57dSAlex Smith if (!(gCPU[i].arch.feature[type] & feature)) 41370ab57dSAlex Smith return false; 42370ab57dSAlex Smith } 43370ab57dSAlex Smith 44370ab57dSAlex Smith return true; 45370ab57dSAlex Smith } 46370ab57dSAlex Smith 47370ab57dSAlex Smith 48370ab57dSAlex Smith static void 49370ab57dSAlex Smith set_intel_syscall_stack(addr_t stackTop) 50370ab57dSAlex Smith { 51370ab57dSAlex Smith x86_write_msr(IA32_MSR_SYSENTER_ESP, stackTop); 52370ab57dSAlex Smith } 53370ab57dSAlex Smith 54370ab57dSAlex Smith 55370ab57dSAlex Smith static void 56370ab57dSAlex Smith init_intel_syscall_registers(void* dummy, int cpuNum) 57370ab57dSAlex Smith { 58370ab57dSAlex Smith x86_write_msr(IA32_MSR_SYSENTER_CS, KERNEL_CODE_SEG); 59370ab57dSAlex Smith x86_write_msr(IA32_MSR_SYSENTER_ESP, 0); 60370ab57dSAlex Smith x86_write_msr(IA32_MSR_SYSENTER_EIP, (addr_t)x86_sysenter); 61370ab57dSAlex Smith 62370ab57dSAlex Smith gX86SetSyscallStack = &set_intel_syscall_stack; 63370ab57dSAlex Smith } 64370ab57dSAlex Smith 65370ab57dSAlex Smith 66370ab57dSAlex Smith #if 0 67370ab57dSAlex Smith static void 68370ab57dSAlex Smith init_amd_syscall_registers(void* dummy, int cpuNum) 69370ab57dSAlex Smith { 70370ab57dSAlex Smith // TODO: ... 71370ab57dSAlex Smith } 72370ab57dSAlex Smith #endif 73370ab57dSAlex Smith 74370ab57dSAlex Smith 75370ab57dSAlex Smith // #pragma mark - 76370ab57dSAlex Smith 77370ab57dSAlex Smith 78370ab57dSAlex Smith void 79370ab57dSAlex Smith x86_initialize_syscall(void) 80370ab57dSAlex Smith { 81*02dd3236SAlex Smith void* syscallCode = (void *)&x86_user_syscall_int; 82*02dd3236SAlex Smith void* syscallCodeEnd = &x86_user_syscall_int_end; 83370ab57dSAlex Smith 84370ab57dSAlex Smith // check syscall 85370ab57dSAlex Smith if (all_cpus_have_feature(FEATURE_COMMON, IA32_FEATURE_SEP) 86370ab57dSAlex Smith && !(gCPU[0].arch.family == 6 && gCPU[0].arch.model < 3 87370ab57dSAlex Smith && gCPU[0].arch.stepping < 3)) { 88370ab57dSAlex Smith // Intel sysenter/sysexit 89370ab57dSAlex Smith dprintf("initialize_commpage_syscall(): sysenter/sysexit supported\n"); 90370ab57dSAlex Smith 91370ab57dSAlex Smith // the code to be used in userland 92*02dd3236SAlex Smith syscallCode = (void *)&x86_user_syscall_sysenter; 93*02dd3236SAlex Smith syscallCodeEnd = &x86_user_syscall_sysenter_end; 94370ab57dSAlex Smith 95370ab57dSAlex Smith // tell all CPUs to init their sysenter/sysexit related registers 96370ab57dSAlex Smith call_all_cpus_sync(&init_intel_syscall_registers, NULL); 97370ab57dSAlex Smith } else if (all_cpus_have_feature(FEATURE_EXT_AMD, 98370ab57dSAlex Smith IA32_FEATURE_AMD_EXT_SYSCALL)) { 99370ab57dSAlex Smith // AMD syscall/sysret 100370ab57dSAlex Smith dprintf("initialize_commpage_syscall(): syscall/sysret supported " 101370ab57dSAlex Smith "-- not yet by Haiku, though"); 102370ab57dSAlex Smith } else { 103370ab57dSAlex Smith // no special syscall support 104370ab57dSAlex Smith dprintf("initialize_commpage_syscall(): no special syscall support\n"); 105370ab57dSAlex Smith } 106370ab57dSAlex Smith 107370ab57dSAlex Smith // fill in the table entry 108370ab57dSAlex Smith size_t len = (size_t)((addr_t)syscallCodeEnd - (addr_t)syscallCode); 109370ab57dSAlex Smith fill_commpage_entry(COMMPAGE_ENTRY_X86_SYSCALL, syscallCode, len); 110370ab57dSAlex Smith 111370ab57dSAlex Smith // add syscall to the commpage image 112370ab57dSAlex Smith image_id image = get_commpage_image(); 113370ab57dSAlex Smith elf_add_memory_image_symbol(image, "commpage_syscall", 114370ab57dSAlex Smith ((addr_t*)USER_COMMPAGE_ADDR)[COMMPAGE_ENTRY_X86_SYSCALL], len, 115370ab57dSAlex Smith B_SYMBOL_TYPE_TEXT); 116370ab57dSAlex Smith } 117