📄 crt0.s
字号:
.file "domcrt0.S"/* * Copyright (C) 1998, 1999, Jonathan S. Shapiro. * * This file is part of the EROS Operating System runtime library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330 Boston, MA 02111-1307, USA. */#include <eros/i486/asm.h>#include <eros/i486/target-asm.h>#include <eros/StdKeyType.h>#include <eros/Key.h>#include <eros/NodeKey.h>#include <eros/ProcessKey.h>#include <eros/Invoke.h>#include <domain/ProtoSpace.h>#include <domain/SpaceBankKey.h>#include <domain/Runtime.h> #define KR_OLDSPACE KR_APP(0)#define KR_NEWSPACE KR_APP(1)#define KR_NEWPAGE KR_APP(2) #define KEYS(k0, k1, k2, k3) (k0 + k1 << 8 + k2 << 16 + k3 << 24) #define NO_KEYS KEYS(KR_VOID, KR_VOID, KR_VOID, KR_VOID) /* Startup code for processes. Handles four cases: 1. Applications that need to construct for themselves a small space. This last class is immutable when first entered. 2. Applications with VCS spaces 3. Applications that run out of a small space which has already been initialized. This uses a special entry point, and applies only to a small number of processes early in the EROS bootstrap process. It probably should NOT be used by other programs. The application is expected to provide the startup code with the information as to which sort of process it is by exporting a symbol called __rt_stack_pages and another called __rt_stack_pointer. These symbols should live in read-only data space. If __rt_stack_pages is nonzero, the startup code first purchases a capage to be the new address space root. It then buys the number of stack pages indicated in __rt_stack_pages and populates the capage with them beginning from slot 15 and working down. If this overwrites your program, too bad -- in that case you should have used a VCS. For programs with a VCS, __rt_stack_pages should be set to zero, as no stack pages need to be explicitly purchased. Once the stack has been fabricated (or not, as the case may be), the startup code loads the value of __rt_stack_pointer into %ESP. (SOON) The startup code then calls the entry point for C++ constructors. This relies on the fact that a dummy stub is provided by crtn.o in the case where this domain was written in C. Finally, the startup code calls main(), at which point control has been transferred to the user's code. (SOON) On exit from main, the startup code calls __exit(), which attempts to self-destruct the process. Since the user has probably left the key registers in a disordered state, this probably fails unless main() has taken appropriate measures to ensure that it succeeds. On entry, we assume that KR_BANK and KR_SELF are set up according to the usual runtime conventions. This code must not damage key registers 0xf (resume key) or 0xc (first key arg). */ .section .rodatasb_alloc_root_node: .long IT_Call .long KR_BANK .long 0 /* snd len */ .long 0 /* snd ptr */ .long NO_KEYS /* snd keys */ .long 0 /* rcv len */ .long 0 /* rcv data */ .long KEYS(KR_NEWSPACE,KR_VOID,KR_VOID,KR_VOID) /* rcv keys */ mk_node_key: .long IT_Call .long KR_NEWSPACE .long 0 /* snd len */ .long 0 /* snd ptr */ .long NO_KEYS /* snd keys */ .long 0 /* rcv len */ .long 0 /* rcv data */ .long KEYS(KR_NEWSPACE,KR_VOID,KR_VOID,KR_VOID) /* rcv keys */buy_first_page: .long IT_Call .long KR_BANK .long 0 /* snd len */ .long 0 /* snd ptr */ .long NO_KEYS /* snd keys */ .long 0 /* rcv len */ .long 0 /* rcv data */ .long KEYS(KR_NEWPAGE,KR_VOID,KR_VOID,KR_VOID) /* rcv keys */ xorl %edi,%edi /* rcv len */ fetch_cur_space: .long IT_Call .long KR_SELF .long 0 /* snd len */ .long 0 /* snd ptr */ .long NO_KEYS /* snd keys */ .long 0 /* rcv len */ .long 0 /* rcv data */ .long KEYS(KR_OLDSPACE,KR_VOID,KR_VOID,KR_VOID) /* rcv keys */ clone_cur_space: .long IT_Call .long KR_NEWSPACE .long 0 /* snd len */ .long 0 /* snd ptr */ .long KEYS(KR_OLDSPACE,KR_VOID,KR_VOID,KR_VOID) /* snd keys */ .long 0 /* rcv len */ .long 0 /* rcv data */ .long NO_KEYS /* rcv keys */ insert_stack_page: .long IT_Call .long KR_NEWSPACE .long 0 /* snd len */ .long 0 /* snd ptr */ .long KEYS(KR_NEWPAGE,KR_VOID,KR_VOID,KR_VOID) /* snd keys */ .long 0 /* rcv len */ .long 0 /* rcv data */ .long NO_KEYS /* rcv keys */ set_my_addr_space: .long IT_Call .long KR_SELF .long 0 /* snd len */ .long 0 /* snd ptr */ .long KEYS(KR_NEWSPACE,KR_VOID,KR_VOID,KR_VOID) /* snd keys */ .long 0 /* rcv len */ .long 0 /* rcv data */ .long NO_KEYS /* rcv keys */ .text#ifdef __ELF__ENTRY(_start)#elseENTRY(start)#endif movl EXT(__rt_stack_pointer),%ESP subl EXT(__rt_stack_keeper_reserve),%ESP /* If it isn't a small space, don't buy stack pages for it or attempt to render data space read-write. */ cmpl $0,EXT(__rt_small_space) jz EXT(__stack_ready) cmpl $0,EXT(__rt_stack_pages) jz EXT(__stack_ready) movl $sb_alloc_root_node,%ebp movl $OC_SpaceBank_Alloc1Node,%eax /* r0 */ xorl %ebx,%ebx /* r1 */ xorl %ecx,%ecx /* r2 */ xorl %edx,%edx /* r3 */ int $0x31 /* invocation trap */ movl $mk_node_key,%ebp movl $OC_Node_MakeNodeKey,%eax /* r0 */ movl $3,%ebx /* Desired BLSS */ xorl %ecx,%ecx /* r2 */ xorl %edx,%edx /* r3 */ int $0x31 /* invocation trap */ /* buy the page while the space bank is still hot in the data cache */ movl $buy_first_page,%ebp movl $OC_SpaceBank_Alloc1DataPage,%eax /* r0 */ xorl %ebx,%ebx /* r1 */ xorl %ecx,%ecx /* r2 */ xorl %edx,%edx /* r3 */ int $0x31 /* invocation trap */ /* fetch current (immutable) address space from our process slot */ movl $fetch_cur_space,%ebp movl $OC_Process_Copy,%eax /* r0 */ movl $ProcAddrSpace,%ebx /* r1 */ xorl %ecx,%ecx /* r2 */ xorl %edx,%edx /* r3 */ int $0x31 /* invocation trap */#if 0 /* check return value */ testl $0,%eax jnz EXT(delete_kept_space)#endif movl $clone_cur_space,%ebp movl $OC_Node_Clone,%eax /* r0 */ xorl %ebx,%ebx /* r1 */ xorl %ecx,%ecx /* r2 */ xorl %edx,%edx /* r3 */ int $0x31 /* invocation trap */#if 0 /* check return value */ testl $0,%eax jnz EXT(delete_kept_space)#endif movl $insert_stack_page,%ebp /* stick the stack page we bought into the new node */ movl $OC_Node_Swap,%eax /* r0 */ movl $EROS_NODE_SLOT_MASK,%ebx /* r1 */ xorl %ecx,%ecx /* r2 */ xorl %edx,%edx /* r3 */ int $0x31 /* invocation trap */ #if 0 /* check return value */ testl $0,%eax jnz EXT(delete_kept_space)#endif movl $set_my_addr_space,%ebp /* Switch to newly copied space -- note no need to change PC! */ movl $OC_Process_Swap,%eax /* r0 */ movl $ProcAddrSpace,%ebx /* r1 */ xorl %ecx,%ecx /* r2 */ xorl %edx,%edx /* r3 */ int $0x31 /* invocation trap */#define NUMPG 0x1FFFC#define PGSLOT 0x1FFF8#define CALLBUF 0x1FFD0 /* WE NOW HAVE A STACK PAGE WE CAN USE FOR COUNTERS!!! */ movl EXT(__rt_stack_pages),%eax movl %eax,NUMPG movl $CALLBUF,%ebp movl $EROS_NODE_SLOT_MASK,PGSLOT /* next slot to write */ LEXT(buy_stack) decl NUMPG /* buy any remaining stack pages we may need... */ jz EXT(__stack_ready) decl PGSLOT movl $OC_SpaceBank_Alloc1DataPage,%eax /* r0 */ xorl %ebx,%ebx /* r1 */ xorl %ecx,%ecx /* r2 */ xorl %edx,%edx /* r3 */ movl $IT_Call,(%ebp) /* inv type */ movl $KR_BANK,4(%ebp) /* invoked key */ movl $0,8(%ebp) /* snd len */ movl $0,12(%ebp) /* snd ptr */ movl $NO_KEYS,16(%ebp) /* snd keys */ movl $0,20(%ebp) /* rcv len */ movl $0,24(%ebp) /* rcv data */ movl $KEYS(KR_NEWPAGE,KR_VOID,KR_VOID,KR_VOID),28(%ebp) /* rcv keys */ int $0x31 /* invocation trap */ /* stick the stack page we bought into the new node */ movl $OC_Node_Swap,%eax /* r0 */ movl PGSLOT,%ebx /* r1 */ xorl %ecx,%ecx /* r2 */ xorl %edx,%edx /* r3 */ movl $NO_KEYS,28(%ebp) /* refuse old pg */ movl $KEYS(KR_NEWPAGE,KR_VOID,KR_VOID,KR_VOID),16(%ebp) /* snd new pg */ movl $KR_NEWSPACE,4(%ebp) /* into new node */ int $0x31 /* invocation trap */#if 0 /* check return value */ testl $0,%eax jnz EXT(delete_kept_space)#endif jmp EXT(buy_stack) ENTRY(__stack_ready) call EXT(__rt_buy_data_space) call EXT(__rt_setup_keeper) ENTRY(start) call EXT(__init) /* so we can __destroy() later */#if defined(__ELF__) && 0 /* someday support C++ */ call EXT(__main)#endif pushl $0 /* envp -- ANSI */ pushl $0 /* argv */ pushl $0 /* argc */ call EXT(main)LEXT(__exit) /* we have exited. destroy() ourselves: */ call EXT(__destroy) /* SHOULD NEVER GET HERE, BUT JUST IN CASE */ hlt .section .keydefs,"aw" .align 4 .type __KEYDEF_LIST_START__,@object /* .size __KEYDEF_LIST_START__,4 */__KEYDEF_LIST_START__:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -