?? passage.c
字號(hào):
/* * This source code is a part of coLinux source package. * * Dan Aloni <da-x@colinux.org>, 2003 (c) * * The code is licensed under the GPL. See the COPYING file at * the root directory. * */ /* * The passage page and code are responsible for switching between the * two operating systems. */ #include <colinux/common/debug.h>#include <colinux/common/libc.h>#include <colinux/common/common.h>#include <colinux/kernel/monitor.h>#include <colinux/arch/passage.h>#include <colinux/os/kernel/alloc.h>#include <colinux/os/kernel/misc.h>#include "cpuid.h"#include "manager.h"#include "utils.h"#include "antinx.h"#include "defs.h"#ifdef __MINGW32__#define SYMBOL_PREFIX "_"#else#define SYMBOL_PREFIX ""#endif#ifdef CO_COLINUX_KERNEL#error "CO_COLINUX_KERNEL should never defined here"#endif#ifdef CONFIG_COOPERATIVE#error "CONFIG_COOPERATIVE should never defined here"#endif/* * These two pseudo variables mark the start and the end of the passage code. * The passage code is position indepedent, so we just copy it from the * driver's text to the passage page which we allocate when we start running. */#define PASSAGE_CODE_WRAP_IBCS(_name_, inner) \extern char _name_; \extern char _name_##_end; \ \static inline unsigned long _name_##_size(void) \{ \ return &_name_##_end - &_name_; \} \ \static inline void memcpy_##_name_(void *dest) \{ \ co_memcpy(dest, &_name_, _name_##_size()); \} \ \asm("" \ ".globl " SYMBOL_PREFIX #_name_ "\n" \ SYMBOL_PREFIX #_name_ ":" "\n" \ " push %ebx" "\n" \ " push %esi" "\n" \ " push %edi" "\n" \ " push %ebp" "\n" \ inner \ " popl %ebp" "\n" \ " popl %edi" "\n" \ " popl %esi" "\n" \ " popl %ebx" "\n" \ " ret" "\n" \ ".globl " SYMBOL_PREFIX #_name_ "_end" "\n" \ SYMBOL_PREFIX #_name_ "_end:;" "\n" \ "");#define PASSAGE_CODE_NOWHERE_LAND_SHORT() \ /* Turn off special processor features */ \ " movl %cr4, %ebx" "\n" \ " andl $0xFFFFFF77, %ebx" "\n" \ " movl %ebx, %cr4" "\n" \/* * Relocate to other map of the passage page. * * We do this by changing the current mapping to the passage temporary * address space, which contains the mapping of the passage page at the * two locations which are specific to the two operating systems. */ \ \/* Put the virtual address of the source passage page in EBX */ \ " movl %ecx, %ebx" "\n" \ " andl $0xFFFFF000, %ebx" "\n" \ \/* * Take the physical address of the temporary address space page directory * pointer and put it in CR3. */ \ " movl (%ebx), %eax" "\n" \ " movl %eax, %cr3" "\n" \/* * Read the 'other_map' field, which is the difference between the two * mappings. */ \ " movl "CO_ARCH_STATE_STACK_OTHERMAP"(%ebp), %eax" "\n" \ \/* * First, we relocate EIP by putting it in 0x64(%ebp). That's why we load * ESP with 0x68(%esp). The call that follows puts the EIP where we want. * Afterwards the EIP is in %(esp) so we relocate it by adding the * relocation offset. We also add the difference between 2 and 3 so that * the 'ret' that follows will put us in 3 intead of 2, but in the other * mapping. */ \ " leal "CO_ARCH_STATE_STACK_RELOCATE_EIP_AFTER"(%ebp), %esp" "\n" \ " call 2f" "\n" \ "2: addl %eax, (%esp)" "\n" \ " addl $3f-2b, (%esp)" "\n" \ " ret" "\n" \ "3: addl %eax, %ecx" "\n" \ " movl %ecx, %ebp" "\n" \#define PASSAGE_CODE_NOWHERE_LAND() \ " movl %ecx, %ebx" "\n" \ " andl $0xFFFFF000, %ebx" "\n" \ " movl (%ebx), %edx" "\n" \ " movl %edx, %eax" "\n" \ " leal "CO_ARCH_STATE_STACK_RELOCATE_EIP_AFTER"(%ebp), %esp" "\n" \ " call 2f" "\n" \ "2: pop %ebx" "\n" \ " andl $0x00000FFF, %ebx" "\n" \ " orl %eax, %ebx" "\n" \ " addl $3f-2b, %ebx" "\n" \ " movl "CO_ARCH_STATE_STACK_TEMP_CR3"(%ebp), %eax" "\n" \ " movl %eax, %cr3" "\n" \ " call *%ebx" "\n" \ " jmp 4f" "\n" \ "3: " "\n" \ " movl "CO_ARCH_STATE_STACK_VA"(%ebp), %eax" "\n" \ " subl %edx, %eax" "\n" \ " subl %eax, %ecx" "\n" \ " subl %eax, %ebp" "\n" \ " subl %eax, (%esp)" "\n" \ " subl %eax, %esp" "\n" \ \ " movl %cr0, %eax" "\n" \ " andl $0x7fffffff, %eax" "\n" \ " movl %eax, %cr0" "\n" \ \ " movl "CO_ARCH_STATE_STACK_CR4"(%ecx), %eax" "\n" \ " andl $0x00000020, %eax" "\n" \ " movl %eax, %cr4" "\n" \ " movl "CO_ARCH_STATE_STACK_TEMP_CR3"(%ecx), %eax" "\n" \ " movl %eax, %cr3" "\n" \ \ " movl %cr0, %eax" "\n" \ " orl $0x80000000, %eax" "\n" \ " movl %eax, %cr0" "\n" \ \ " movl "CO_ARCH_STATE_STACK_VA"(%ecx), %eax" "\n" \ " subl %edx, %eax" "\n" \ " addl %eax, %esp" "\n" \ " addl %eax, (%esp)" "\n" \ " addl %eax, %ecx" "\n" \ " movl %ecx, %ebp" "\n" \ " ret" "\n" \ \ " 4:\n" \#define PASSAGE_CODE_WRAP_SWITCH(_inner_) \/* read return address and state pointers */ \ " movl 16(%esp), %ebx" /* return addr */ "\n" \ " movl 24(%esp), %ebp" /* current */ "\n" \ " movl 28(%esp), %ecx" /* other */ "\n" \ \/* save flags, disable interrupts */ \ " pushfl" "\n" \ " cli" "\n" \ \/* save and switch from old esp */ \ " movl %esp, "CO_ARCH_STATE_STACK_ESP"(%ebp)" "\n" \ " mov %ss, "CO_ARCH_STATE_STACK_SS"(%ebp)" "\n" \ \/* save flags */ \ " movl (%esp), %eax" "\n" \ " movl %eax, "CO_ARCH_STATE_STACK_FLAGS"(%ebp)" "\n" \ \/* save return address */ \ " movl %ebx, "CO_ARCH_STATE_STACK_RETURN_EIP"(%ebp)" "\n" \ \/* save %cs */ \ " movl %cs, %ebx" "\n" \ " movl %ebx, "CO_ARCH_STATE_STACK_CS"(%ebp)" "\n" \ \ _inner_ \ \/* get old ESP in EAX */ \ " lss "CO_ARCH_STATE_STACK_ESP"(%ebp), %eax" "\n" \ \/* get return address */ \ " movl "CO_ARCH_STATE_STACK_RETURN_EIP"(%ebp), %ebx" "\n" \ " movl %ebx, 20(%eax)" "\n" \ \/* get flags */ \ " movl "CO_ARCH_STATE_STACK_FLAGS"(%ebp), %ebx" "\n" \ " movl %ebx, (%eax)" "\n" \ \/* switch to old ESP */ \ " lss "CO_ARCH_STATE_STACK_ESP"(%ebp), %esp" "\n" \ \ " call 1f" "\n" \ "1: popl %eax" "\n" \ " addl $2f-1b,%eax" "\n" \ " movl 0x04(%ebp), %ebx" "\n" \ " movw %bx, -2(%eax)" "\n" \ " movl %eax, -6(%eax)" "\n" \ " jmp 3f" "\n" \ "3: ljmp $0,$0" "\n" \ "2: popfl" "\n"#define PASSAGE_PAGE_PRESERVATION_FXSAVE(_inner_) \ " fxsave "CO_ARCH_STATE_STACK_FXSTATE"(%ebp)" "\n" \ " fnclex" "\n" \ _inner_ \ " fxrstor "CO_ARCH_STATE_STACK_FXSTATE"(%ebp)" "\n"#define PASSAGE_PAGE_PRESERVATION_FNSAVE(_inner_) \ " fnsave "CO_ARCH_STATE_STACK_FXSTATE"(%ebp)" "\n" \ " fwait" "\n" \ _inner_ \ " frstor "CO_ARCH_STATE_STACK_FXSTATE"(%ebp)" "\n"#define PASSAGE_PAGE_PRESERVATION_DEBUG(_inner_) \/* Put the virtual address of the passage page in EBX */ \ " movl %ebp, %ebx" "\n" \ " andl $0xFFFFF000, %ebx" "\n" \/* " incb 0x20f(%ebx)" "\n" */ \ \/* save DR0 */ \ " movl %dr0, %eax" "\n" \ " movl %eax, "CO_ARCH_STATE_STACK_DR0"(%ebp)" "\n" \ " movl %eax, 0x4(%ebx)" "\n" \ \/* save DR1 */ \ " movl %dr1, %eax" "\n" \ " movl %eax, "CO_ARCH_STATE_STACK_DR1"(%ebp)" "\n" \ " movl %eax, 0x8(%ebx)" "\n" \ \/* save DR2 */ \ " movl %dr2, %eax" "\n" \ " movl %eax, "CO_ARCH_STATE_STACK_DR2"(%ebp)" "\n" \ " movl %eax, 0xc(%ebx)" "\n" \ \/* save DR3 */ \ " movl %dr3, %eax" "\n" \ " movl %eax, "CO_ARCH_STATE_STACK_DR3"(%ebp)" "\n" \ " movl %eax, 0x10(%ebx)" "\n" \ \/* save DR6 */ \ " movl %dr6, %eax" "\n" \ " movl %eax, "CO_ARCH_STATE_STACK_DR6"(%ebp)" "\n" \ " movl %eax, 0x14(%ebx)" "\n" \ \/* save DR7 */ \ " movl %dr7, %eax" "\n" \ " movl %eax, "CO_ARCH_STATE_STACK_DR7"(%ebp)" "\n" \ " movl $0x00000700, %eax" "\n" \ " movl %eax, 0x18(%ebx)" "\n" \ " movl %eax, %dr7" "\n" \ \ _inner_ \ \/* Put the virtual address of the passage page in EBX */ \ " movl %ebp, %ebx" "\n" \ " andl $0xFFFFF000, %ebx" "\n" \ \/* load DR0 */ \ " movl "CO_ARCH_STATE_STACK_DR0"(%ebp), %eax" "\n" \ " movl 0x4(%ebx), %ecx" "\n" \ " cmpl %eax, %ecx" "\n" \ " jz 1f" "\n" \ " movl %eax, %dr0" "\n" \ "1:" "\n" \ \/* load DR1 */ \ " movl "CO_ARCH_STATE_STACK_DR1"(%ebp), %eax" "\n" \ " movl 0x8(%ebx), %ecx" "\n" \ " cmpl %eax, %ecx" "\n" \ " jz 1f" "\n" \ " movl %eax, %dr1" "\n" \ "1:" "\n" \ \/* load DR2 */ \ " movl "CO_ARCH_STATE_STACK_DR2"(%ebp), %eax" "\n" \ " movl 0xC(%ebx), %ecx" "\n" \ " cmpl %eax, %ecx" "\n" \ " jz 1f" "\n" \ " movl %eax, %dr2" "\n" \ "1:" "\n" \ \/* load DR3 */ \ " movl "CO_ARCH_STATE_STACK_DR3"(%ebp), %eax" "\n" \ " movl 0x10(%ebx), %ecx" "\n" \ " cmpl %eax, %ecx" "\n" \ " jz 1f" "\n" \ " movl %eax, %dr3" "\n" \ "1:" "\n" \ \/* load DR6 */ \ " movl "CO_ARCH_STATE_STACK_DR6"(%ebp), %eax" "\n" \ " movl 0x14(%ebx), %ecx" "\n" \ " cmpl %eax, %ecx" "\n" \ " jz 1f" "\n" \ " movl %eax, %dr6" "\n" \ "1:" "\n" \ \/* load DR7 */ \ " movl "CO_ARCH_STATE_STACK_DR7"(%ebp), %eax" "\n" \ " movl 0x18(%ebx), %ecx" "\n" \ " cmpl %eax, %ecx" "\n" \ " jz 1f" "\n" \ " movl %eax, %dr7" "\n" \ "1:" "\n" \#define PASSAGE_PAGE_PRESERVATION_COMMON(_inner_) \/* save GDT */ \ " leal "CO_ARCH_STATE_STACK_GDT"(%ebp), %ebx" "\n" \ " sgdt (%ebx)" "\n" \ \/* save TR */ \ " xor %eax, %eax" "\n" \ " str %ax" "\n" \ " movw %ax, "CO_ARCH_STATE_STACK_TR"(%ebp)" "\n" \ \/* \ * If TR is not 0, turn off our task's BUSY bit so we don't get a GPF \ * on the way back. \ */ \ " cmpw $0, %ax" "\n" \ " jz 1f" "\n" \ " movl 2(%ebx), %edx" "\n" \ " shr $3, %eax " "\n" \ " andl $0xfffffdff, 4(%edx,%eax,8)" "\n" \ "1:" "\n" \ \/* save LDT */ \ " sldt "CO_ARCH_STATE_STACK_LDT"(%ebp)" "\n" \ \/* save IDT */ \ " sidt "CO_ARCH_STATE_STACK_IDT"(%ebp)" "\n" \ \/* save segment registers */ \ " movl %gs, %ebx" "\n" \ " movl %ebx, "CO_ARCH_STATE_STACK_GS"(%ebp)" "\n" \ " movl %fs, %ebx" "\n" \ " movl %ebx, "CO_ARCH_STATE_STACK_FS"(%ebp)" "\n" \ " movl %ds, %ebx" "\n" \ " movl %ebx, "CO_ARCH_STATE_STACK_DS"(%ebp)" "\n" \ " movl %es, %ebx" "\n" \ " movl %ebx, "CO_ARCH_STATE_STACK_ES"(%ebp)" "\n" \ \/* be on the safe side and nullify the segment registers */ \ " movl $0, %ebx" "\n" \ " movl %ebx, %fs" "\n" \ " movl %ebx, %gs" "\n" \ \/* save CR4 */ \ " movl %cr4, %eax" "\n" \ " movl %eax, "CO_ARCH_STATE_STACK_CR4"(%ebp)" "\n" \ \/* save CR2 */ \ " movl %cr2, %eax" "\n" \ " movl %eax, "CO_ARCH_STATE_STACK_CR2"(%ebp)" "\n" \ \/* save CR0 */ \ " movl %cr0, %eax" "\n" \ " movl %eax, "CO_ARCH_STATE_STACK_CR0"(%ebp)" "\n" \ \/* save CR3 */ \ " movl %cr3, %eax" "\n" \ " movl %eax, "CO_ARCH_STATE_STACK_CR3"(%ebp)" "\n" \ \_inner_ \/* load other's CR4 */ \ " movl "CO_ARCH_STATE_STACK_CR4"(%ebp), %eax" "\n" \ " movl %eax, %cr4" "\n" \ \
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -