📄 w32entry.s
字号:
/* * w32entry.S * * Copyright (C) 2006 Insigme Co., Ltd * * Authors: * - Decao Mao, Chenzhan Hu, Lixing Chu, Zhiqiang Jiao * * This software has been developed while working on the Linux Unified Kernel * project (http://linux.insigma.com.cn) in the Insigma Reaserch Institute, * which is a subdivision of Insigma Co., Ltd (http://www.insigma.com.cn). * * The project is sponsored by Insigma Co., Ltd. * * The authors can be reached at linux@insigma.com.cn. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * Revision History: * Jan 2006 - Created. */ /* * Implements the w32 system call mechanism. The code is basically * a merge of the related code in entry.S from Linux 2.6.13 and * in syscall.S from Reactos 0.2.6. It is for i386 only. */#include "config.h"#include <linux/linkage.h>#include <asm/thread_info.h>#include <asm/errno.h>#include <asm/segment.h>#include <asm/smp.h>#include <asm/page.h>#include <asm/desc.h>#include "irq_vectors.h"#ifndef TI_flags#define TI_flags 8#endif#define nr_syscalls ((syscall_table_size)/4)EBX = 0x00ECX = 0x04EDX = 0x08ESI = 0x0CEDI = 0x10EBP = 0x14EAX = 0x18DS = 0x1CES = 0x20ORIG_EAX = 0x24EIP = 0x28CS = 0x2CEFLAGS = 0x30OLDESP = 0x34OLDSS = 0x38CF_MASK = 0x00000001TF_MASK = 0x00000100IF_MASK = 0x00000200DF_MASK = 0x00000400 NT_MASK = 0x00004000VM_MASK = 0x00020000#ifdef CONFIG_PREEMPT#define preempt_stop cli#else#define preempt_stop#define resume_kernel restore_nocheck#endif#define SAVE_ALL \ cld; \ pushl %es; \ pushl %ds; \ pushl %eax; \ pushl %ebp; \ pushl %edi; \ pushl %esi; \ pushl %edx; \ pushl %ecx; \ pushl %ebx; \ movl $(__USER_DS), %ecx; \ movl %ecx, %ds; \ movl %ecx, %es;#define RESTORE_INT_REGS \ popl %ebx; \ popl %ecx; \ popl %edx; \ popl %esi; \ popl %edi; \ popl %ebp; \ popl %eax#define RESTORE_REGS \ RESTORE_INT_REGS; \1: popl %ds; \2: popl %es; \.section .fixup,"ax"; \3: movl $0,(%esp); \ jmp 1b; \4: movl $0,(%esp); \ jmp 2b; \.previous; \.section __ex_table,"a";\ .align 4; \ .long 1b,3b; \ .long 2b,4b; \.previous#ifdef CONFIG_UNIFIED_KERNELENTRY(w32system_call) pushl %eax # save orig_eax SAVE_ALL GET_THREAD_INFO(%ebp) # previous mode tracing to be implemented # system call tracing in operation / emulation /* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */ testw $(_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp) jnz w32syscall_trace_entry /* * Find out which syscall table (basic or extended) to use, * and get the offset to the table. * The offset is related to the Table Index as such: * offset = TableIndex x 0x10. (see the typedef for SSDT_ENTRY) * For example, if %eax is 0x1124, then the offset is 0x10. */ movl %eax, %edi shrl $8, %edi andl $0x10, %edi /* Now add the base system table to the offset */ addl $(KeServiceDescriptorTable), %edi /* Get the true syscall ID and check it */ andl $0x0FFF, %eax cmpl 8(%edi), %eax /* Invalid ID, try to load Win32K Table */ jnb w32syscall_badsys w32syscall_call: /* For w32syscall_trace_back */ /* Users's current stack frame pointer is source */ #movl OLDESP(%esp), %edx #addl $8, %edx #for parameters on the user space stack movl %edx, %esi /* Allocate room for argument list from kernel stack */ movl 12(%edi), %ecx movb (%ecx, %eax), %cl movzx %cl, %ecx shll $2,%ecx/*get actually byte size*/ /* Allocate new Kernel stack frame */ pushl %ebp movl %esp,%ebp /* Allocate space on our stack ,ecx is the size of stack buffer to copy*/ subl %ecx, %esp /* Get pointer to function */ movl (%edi), %edi movl (%edi, %eax, 4), %eax /* Copy the arguments from the user stack to kernel stack */ shr $2, %ecx/*count of dword vaule to copy ecx = ecx/4 */ movl %esp, %edi cld rep movsd #movl %esp,%edi #addl $8,%esp /*pushl %eax; pushl %ebp; pushl %edi; pushl %esi; pushl %edx; pushl %ecx; pushl %ebx; mov %ecx,%esi call check_kernel popl %ebx; popl %ecx; popl %edx; popl %esi; popl %edi; popl %ebp; popl %eax*/ /* Do the System Call */ call *%eax /* Deallocate the kernel stack frame */ movl %ebp, %esp popl %ebp movl %eax,EAX(%esp) # store the return valuew32syscall_exit: cli # make sure we don't miss an interrupt # setting need_resched or sigpending # between sampling and the iret movl TI_flags(%ebp), %ecx testw $_TIF_ALLWORK_MASK, %cx # current->work jne w32syscall_exit_workw32restore_all: movl EFLAGS(%esp), %eax # mix EFLAGS, SS and CS # Warning: OLDSS(%esp) contains the wrong/random values if we # are returning to the kernel. # See comments in process.c:copy_thread() for details. movb OLDSS(%esp), %ah movb CS(%esp), %al andl $(VM_MASK | (4 << 8) | 3), %eax cmpl $((4 << 8) | 3), %eax je w32ldt_ss # returning to user-space with LDT SS w32restore_nocheck: RESTORE_REGS addl $4, %esp iretw32ldt_ss: larl OLDSS(%esp), %eax jnz w32restore_nocheck testl $0x00400000, %eax # returning to 32bit stack? jnz w32restore_nocheck # allright, normal return /* If returning to userspace with 16bit stack, * try to fix the higher word of ESP, as the CPU * won't restore it. * This is an "official" bug of all the x86-compatible * CPUs, which we can try to work around to make * dosemu and wine happy. */ subl $8, %esp # reserve space for switch16 pointer cli movl %esp, %eax /* Set up the 16bit stack frame with switch32 pointer on top, * and a switch16 pointer on top of the current frame. */ #call setup_x86_bogus_stack RESTORE_REGS lss 20+4(%esp), %esp # switch to 16bit stack iret # perform work that needs to be done immediately before resumption ALIGN w32work_pending: testb $_TIF_NEED_RESCHED, %cl jz w32work_notifysig w32work_resched: call schedule cli # make sure we don't miss an interrupt # setting need_resched or sigpending # between sampling and the iret movl TI_flags(%ebp), %ecx andl $_TIF_WORK_MASK, %ecx # is there any work to be done other # than syscall tracing? jz w32restore_all testb $_TIF_NEED_RESCHED, %cl jnz w32work_resched w32work_notifysig: # deal with pending signals and # notify-resume requests testl $VM_MASK, EFLAGS(%esp) # user-space or vm86-space movl %esp, %eax jne w32work_notifysig_v86 xorl %edx, %edx call do_apc # for Windows APC call do_notify_resume # for Linux signals jmp w32resume_userspace ALIGN w32work_notifysig_v86: pushl %ecx call save_v86_state popl %ecx movl %eax,%esp xorl %edx,%edx call do_apc call do_notify_resume jmp w32resume_userspace #perform syscall exit tracing ALIGN w32syscall_trace_entry: movl $-ENOSYS,EAX(%esp) movl %esp, %eax xorl %edx,%edx call do_syscall_trace cmpl $0, %eax jne w32resume_userspace # ret != 0 -> running under PTRACE_SYSEMU, # so must skip actual syscall movl ORIG_EAX(%esp), %eax /* back to w32syscall_call */ movl %eax, %edi shrl $8, %edi andl $0x10, %edi addl $(KeServiceDescriptorTable), %edi andl $0x0FFF, %eax cmpl 8(%edi), %eax jb w32syscall_call jmp w32syscall_exit# perform syscall exit tracing ALIGN w32syscall_exit_work: testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP), %cl jz w32work_pending sti # could let do_syscall_trace() call # schedule() instead movl %esp, %eax movl $1, %edx call do_syscall_trace jmp w32resume_userspace ENTRY(w32resume_userspace) cli # make sure we don't miss an interrupt # setting need_resched or sigpending # between sampling and the iret movl TI_flags(%ebp), %ecx andl $_TIF_WORK_MASK, %ecx # is there any work to be done on # int/exception return? jne w32work_pending # previous mode restoration to be implemented jmp w32restore_all ALIGN w32syscall_badsys: movl $-ENOSYS,EAX(%esp) jmp w32resume_userspace #endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -