|
|
Darwin 0.1 Mach+BSD kernel
/* * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights * Reserved. This file contains Original Code and/or Modifications of * Original Code as defined in and that are subject to the Apple Public * Source License Version 1.1 (the "License"). You may not use this file * except in compliance with the License. Please obtain a copy of the * License at http://www.apple.com/publicsource and read it before using * this file. * * The Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * Copyright (c) 1992 NeXT Computer, Inc. * * Locore module for NEXTSTEP/Intel Kernel. * * HISTORY * * 17 July 1994 ? at NeXT * Major mods for user state save optimizations. * 29 August 1992 ? at NeXT * Created. */ #import <architecture/i386/asm_help.h> #import <assym.h> TEXT #define EXCEPTION(name, number) \ LEAF(_##name, 0) ; \ pushl $0x00 ; \ pushl $##number ; \ jmp trap_handler #define EXCEPTERR(name, number) \ LEAF(_##name, 0) ; \ pushl $##number ; \ jmp trap_handler #define INTERRUPT(name, number) \ LEAF(_##name, 0) ; \ pushl $0x00 ; \ pushl $##number ; \ jmp interrupt #define RETURN \ popl %gs ; \ popl %fs ; \ popl %es ; \ popl %ds ; \ popa ; \ addl $8, %esp ; \ iret EXCEPTION(trp_divr,0x00) EXCEPTION(trp_debg,0x01) EXCEPTION(int__nmi,0x02) EXCEPTION(trp_brpt,0x03) EXCEPTION(trp_over,0x04) EXCEPTION(flt_bnds,0x05) EXCEPTION(flt_opcd,0x06) EXCEPTION(flt_ncpr,0x07) EXCEPTERR(abt_dblf,0x08) EXCEPTION(abt_over,0x09) EXCEPTERR(flt_btss,0x0A) EXCEPTERR(flt_bseg,0x0B) EXCEPTERR(flt_bstk,0x0C) EXCEPTERR(flt_prot,0x0D) EXCEPTERR(flt_page,0x0E) EXCEPTION(trp_0x0F,0x0F) EXCEPTION(flt_bcpr,0x10) EXCEPTION(trp_0x11,0x11) EXCEPTION(trp_0x12,0x12) EXCEPTION(trp_0x13,0x13) EXCEPTION(trp_0x14,0x14) EXCEPTION(trp_0x15,0x15) EXCEPTION(trp_0x16,0x16) EXCEPTION(trp_0x17,0x17) EXCEPTION(trp_0x18,0x18) EXCEPTION(trp_0x19,0x19) EXCEPTION(trp_0x1A,0x1A) EXCEPTION(trp_0x1B,0x1B) EXCEPTION(trp_0x1C,0x1C) EXCEPTION(trp_0x1D,0x1D) EXCEPTION(trp_0x1E,0x1E) EXCEPTION(trp_0x1F,0x1F) EXCEPTION(trp_0x20,0x20) EXCEPTION(trp_0x21,0x21) EXCEPTION(trp_0x22,0x22) EXCEPTION(trp_0x23,0x23) EXCEPTION(trp_0x24,0x24) EXCEPTION(trp_0x25,0x25) EXCEPTION(trp_0x26,0x26) EXCEPTION(trp_0x27,0x27) EXCEPTION(trp_0x28,0x28) EXCEPTION(trp_0x29,0x29) EXCEPTION(trp_0x2A,0x2A) EXCEPTION(trp_0x2B,0x2B) EXCEPTION(trp_0x2C,0x2C) EXCEPTION(trp_0x2D,0x2D) EXCEPTION(trp_0x2E,0x2E) EXCEPTION(trp_0x2F,0x2F) EXCEPTION(trp_0x30,0x30) EXCEPTION(trp_0x31,0x31) EXCEPTION(trp_0x32,0x32) EXCEPTION(trp_0x33,0x33) EXCEPTION(trp_0x34,0x34) EXCEPTION(trp_0x35,0x35) EXCEPTION(trp_0x36,0x36) EXCEPTION(trp_0x37,0x37) EXCEPTION(trp_0x38,0x38) EXCEPTION(trp_0x39,0x39) EXCEPTION(trp_0x3A,0x3A) EXCEPTION(trp_0x3B,0x3B) EXCEPTION(trp_0x3C,0x3C) EXCEPTION(trp_0x3D,0x3D) EXCEPTION(trp_0x3E,0x3E) EXCEPTION(trp_0x3F,0x3F) // INTERRUPT(int_0x40,0x40) INTERRUPT(int_0x41,0x41) INTERRUPT(int_0x42,0x42) INTERRUPT(int_0x43,0x43) INTERRUPT(int_0x44,0x44) INTERRUPT(int_0x45,0x45) INTERRUPT(int_0x46,0x46) INTERRUPT(int_0x47,0x47) INTERRUPT(int_0x48,0x48) INTERRUPT(int_0x49,0x49) INTERRUPT(int_0x4A,0x4A) INTERRUPT(int_0x4B,0x4B) INTERRUPT(int_0x4C,0x4C) INTERRUPT(int_0x4D,0x4D) INTERRUPT(int_0x4E,0x4E) INTERRUPT(int_0x4F,0x4F) INTERRUPT(int_0x50,0x50) INTERRUPT(int_0x51,0x51) INTERRUPT(int_0x52,0x52) INTERRUPT(int_0x53,0x53) INTERRUPT(int_0x54,0x54) INTERRUPT(int_0x55,0x55) INTERRUPT(int_0x56,0x56) INTERRUPT(int_0x57,0x57) INTERRUPT(int_0x58,0x58) INTERRUPT(int_0x59,0x59) INTERRUPT(int_0x5A,0x5A) INTERRUPT(int_0x5B,0x5B) INTERRUPT(int_0x5C,0x5C) INTERRUPT(int_0x5D,0x5D) INTERRUPT(int_0x5E,0x5E) INTERRUPT(int_0x5F,0x5F) INTERRUPT(int_0x60,0x60) INTERRUPT(int_0x61,0x61) INTERRUPT(int_0x62,0x62) INTERRUPT(int_0x63,0x63) INTERRUPT(int_0x64,0x64) INTERRUPT(int_0x65,0x65) INTERRUPT(int_0x66,0x66) INTERRUPT(int_0x67,0x67) INTERRUPT(int_0x68,0x68) INTERRUPT(int_0x69,0x69) INTERRUPT(int_0x6A,0x6A) INTERRUPT(int_0x6B,0x6B) INTERRUPT(int_0x6C,0x6C) INTERRUPT(int_0x6D,0x6D) INTERRUPT(int_0x6E,0x6E) INTERRUPT(int_0x6F,0x6F) INTERRUPT(int_0x70,0x70) INTERRUPT(int_0x71,0x71) INTERRUPT(int_0x72,0x72) INTERRUPT(int_0x73,0x73) INTERRUPT(int_0x74,0x74) INTERRUPT(int_0x75,0x75) INTERRUPT(int_0x76,0x76) INTERRUPT(int_0x77,0x77) INTERRUPT(int_0x78,0x78) INTERRUPT(int_0x79,0x79) INTERRUPT(int_0x7A,0x7A) INTERRUPT(int_0x7B,0x7B) INTERRUPT(int_0x7C,0x7C) INTERRUPT(int_0x7D,0x7D) INTERRUPT(int_0x7E,0x7E) INTERRUPT(int_0x7F,0x7F) INTERRUPT(int_0x80,0x80) INTERRUPT(int_0x81,0x81) INTERRUPT(int_0x82,0x82) INTERRUPT(int_0x83,0x83) INTERRUPT(int_0x84,0x84) INTERRUPT(int_0x85,0x85) INTERRUPT(int_0x86,0x86) INTERRUPT(int_0x87,0x87) INTERRUPT(int_0x88,0x88) INTERRUPT(int_0x89,0x89) INTERRUPT(int_0x8A,0x8A) INTERRUPT(int_0x8B,0x8B) INTERRUPT(int_0x8C,0x8C) INTERRUPT(int_0x8D,0x8D) INTERRUPT(int_0x8E,0x8E) INTERRUPT(int_0x8F,0x8F) INTERRUPT(int_0x90,0x90) INTERRUPT(int_0x91,0x91) INTERRUPT(int_0x92,0x92) INTERRUPT(int_0x93,0x93) INTERRUPT(int_0x94,0x94) INTERRUPT(int_0x95,0x95) INTERRUPT(int_0x96,0x96) INTERRUPT(int_0x97,0x97) INTERRUPT(int_0x98,0x98) INTERRUPT(int_0x99,0x99) INTERRUPT(int_0x9A,0x9A) INTERRUPT(int_0x9B,0x9B) INTERRUPT(int_0x9C,0x9C) INTERRUPT(int_0x9D,0x9D) INTERRUPT(int_0x9E,0x9E) INTERRUPT(int_0x9F,0x9F) INTERRUPT(int_0xA0,0xA0) INTERRUPT(int_0xA1,0xA1) INTERRUPT(int_0xA2,0xA2) INTERRUPT(int_0xA3,0xA3) INTERRUPT(int_0xA4,0xA4) INTERRUPT(int_0xA5,0xA5) INTERRUPT(int_0xA6,0xA6) INTERRUPT(int_0xA7,0xA7) INTERRUPT(int_0xA8,0xA8) INTERRUPT(int_0xA9,0xA9) INTERRUPT(int_0xAA,0xAA) INTERRUPT(int_0xAB,0xAB) INTERRUPT(int_0xAC,0xAC) INTERRUPT(int_0xAD,0xAD) INTERRUPT(int_0xAE,0xAE) INTERRUPT(int_0xAF,0xAF) INTERRUPT(int_0xB0,0xB0) INTERRUPT(int_0xB1,0xB1) INTERRUPT(int_0xB2,0xB2) INTERRUPT(int_0xB3,0xB3) INTERRUPT(int_0xB4,0xB4) INTERRUPT(int_0xB5,0xB5) INTERRUPT(int_0xB6,0xB6) INTERRUPT(int_0xB7,0xB7) INTERRUPT(int_0xB8,0xB8) INTERRUPT(int_0xB9,0xB9) INTERRUPT(int_0xBA,0xBA) INTERRUPT(int_0xBB,0xBB) INTERRUPT(int_0xBC,0xBC) INTERRUPT(int_0xBD,0xBD) INTERRUPT(int_0xBE,0xBE) INTERRUPT(int_0xBF,0xBF) INTERRUPT(int_0xC0,0xC0) INTERRUPT(int_0xC1,0xC1) INTERRUPT(int_0xC2,0xC2) INTERRUPT(int_0xC3,0xC3) INTERRUPT(int_0xC4,0xC4) INTERRUPT(int_0xC5,0xC5) INTERRUPT(int_0xC6,0xC6) INTERRUPT(int_0xC7,0xC7) INTERRUPT(int_0xC8,0xC8) INTERRUPT(int_0xC9,0xC9) INTERRUPT(int_0xCA,0xCA) INTERRUPT(int_0xCB,0xCB) INTERRUPT(int_0xCC,0xCC) INTERRUPT(int_0xCD,0xCD) INTERRUPT(int_0xCE,0xCE) INTERRUPT(int_0xCF,0xCF) INTERRUPT(int_0xD0,0xD0) INTERRUPT(int_0xD1,0xD1) INTERRUPT(int_0xD2,0xD2) INTERRUPT(int_0xD3,0xD3) INTERRUPT(int_0xD4,0xD4) INTERRUPT(int_0xD5,0xD5) INTERRUPT(int_0xD6,0xD6) INTERRUPT(int_0xD7,0xD7) INTERRUPT(int_0xD8,0xD8) INTERRUPT(int_0xD9,0xD9) INTERRUPT(int_0xDA,0xDA) INTERRUPT(int_0xDB,0xDB) INTERRUPT(int_0xDC,0xDC) INTERRUPT(int_0xDD,0xDD) INTERRUPT(int_0xDE,0xDE) INTERRUPT(int_0xDF,0xDF) INTERRUPT(int_0xE0,0xE0) INTERRUPT(int_0xE1,0xE1) INTERRUPT(int_0xE2,0xE2) INTERRUPT(int_0xE3,0xE3) INTERRUPT(int_0xE4,0xE4) INTERRUPT(int_0xE5,0xE5) INTERRUPT(int_0xE6,0xE6) INTERRUPT(int_0xE7,0xE7) INTERRUPT(int_0xE8,0xE8) INTERRUPT(int_0xE9,0xE9) INTERRUPT(int_0xEA,0xEA) INTERRUPT(int_0xEB,0xEB) INTERRUPT(int_0xEC,0xEC) INTERRUPT(int_0xED,0xED) INTERRUPT(int_0xEE,0xEE) INTERRUPT(int_0xEF,0xEF) INTERRUPT(int_0xF0,0xF0) INTERRUPT(int_0xF1,0xF1) INTERRUPT(int_0xF2,0xF2) INTERRUPT(int_0xF3,0xF3) INTERRUPT(int_0xF4,0xF4) INTERRUPT(int_0xF5,0xF5) INTERRUPT(int_0xF6,0xF6) INTERRUPT(int_0xF7,0xF7) INTERRUPT(int_0xF8,0xF8) INTERRUPT(int_0xF9,0xF9) INTERRUPT(int_0xFA,0xFA) INTERRUPT(int_0xFB,0xFB) INTERRUPT(int_0xFC,0xFC) INTERRUPT(int_0xFD,0xFD) INTERRUPT(int_0xFE,0xFE) INTERRUPT(int_0xFF,0xFF) ALIGN trap_handler: // save general registers pusha // save segment registers pushl %ds pushl %es pushl %fs pushl %gs // reinitialize segment registers movw $ KDSSEL,%ax movw %ax,%ds movw %ax,%es movw $ LDATASEL,%ax movw %ax,%fs movw $ NULLSEL,%ax movw %ax,%gs // clear direction flag cld // set frame pointer lea EBP(%esp),%ebp // is our stack the save area? movl _empty_stacks,%esi movl %esp,%ebx andl %esi,%esi je 0f // yes, switch to kernel stack // need to do this atomically cli movl _stack_pointers,%esp movl $0,_empty_stacks sti 0: // ptr to saved state pushl %ebx call _catch_trap // user mode trap never returns // kernel mode trap always returns // restore old stack pointer // and old value of _empty_stacks // need to do this atomically cli movl %ebx,%esp movl %esi,_empty_stacks sti RETURN ALIGN interrupt: // save general registers pusha // save segment registers pushl %ds pushl %es pushl %fs pushl %gs // reinitialize segment registers movw $ KDSSEL,%ax movw %ax,%ds movw %ax,%es movw $ LDATASEL,%ax movw %ax,%fs movw $ NULLSEL,%ax movw %ax,%gs // clear direction flag cld // set frame pointer lea EBP(%esp),%ebp // is our stack the save area? movl _empty_stacks,%esi movl %esp,%ebx andl %esi,%esi je 0f // yes, switch to kernel stack // interrupts are already disabled movl _stack_pointers,%esp movl $0,_empty_stacks 0: // ptr to saved state pushl %ebx call _catch_interrupt // user mode interrupt may not return // kernel mode interrupt always returns // restore old stack pointer movl %ebx,%esp // restore old value of _empty_stacks movl %esi,_empty_stacks RETURN LEAF(_machdep_call_, 0) // save eflags pushf // dummy trapno pushl $0 // save general registers pusha // save segment registers pushl %ds pushl %es pushl %fs pushl %gs // copy eflags to correct offset movl ERR(%esp),%eax movl %eax,EFL(%esp) // reinitialize segment registers movw $ KDSSEL,%ax movw %ax,%ds movw %ax,%es movw $ LDATASEL,%ax movw %ax,%fs movw $ NULLSEL,%ax movw %ax,%gs // clear direction flag cld // set frame pointer lea EBP(%esp),%ebp // is our stack the save area? movl _empty_stacks,%esi movl %esp,%ebx andl %esi,%esi je 0f // yes, switch to kernel stack // need to do this atomically cli movl _stack_pointers,%esp movl $0,_empty_stacks sti 0: // ptr to saved state pushl %ebx call _machdep_call // call from user mode never returns // call from kernel mode always returns (error) movl %ebx,%esp RETURN LEAF(_mach_kernel_trap_, 0) // save eflags pushf // dummy trapno pushl $0 // save general registers pusha // save segment registers pushl %ds pushl %es pushl %fs pushl %gs // copy eflags to correct offset movl ERR(%esp),%eax movl %eax,EFL(%esp) // reinitialize segment registers movw $ KDSSEL,%ax movw %ax,%ds movw %ax,%es movw $ LDATASEL,%ax movw %ax,%fs movw $ NULLSEL,%ax movw %ax,%gs // clear direction flag cld // set frame pointer lea EBP(%esp),%ebp // is our stack the save area? movl _empty_stacks,%esi movl %esp,%ebx andl %esi,%esi je 0f // yes, switch to kernel stack // need to do this atomically cli movl _stack_pointers,%esp movl $0,_empty_stacks sti 0: // ptr to saved state pushl %ebx call _mach_kernel_trap // call from user mode never returns // call from kernel mode always returns (error) movl %ebx,%esp RETURN LEAF(_unix_syscall_, 0) // save eflags pushf // dummy trapno pushl $0 // save general registers pusha // save segment registers pushl %ds pushl %es pushl %fs pushl %gs // copy eflags to correct offset movl ERR(%esp),%eax movl %eax,EFL(%esp) // reinitialize segment registers movw $ KDSSEL,%ax movw %ax,%ds movw %ax,%es movw $ LDATASEL,%ax movw %ax,%fs movw $ NULLSEL,%ax movw %ax,%gs // clear direction flag cld // set frame pointer lea EBP(%esp),%ebp // is our stack the save area? movl _empty_stacks,%esi movl %esp,%ebx andl %esi,%esi je 0f // yes, switch to kernel stack // need to do this atomically cli movl _stack_pointers,%esp movl $0,_empty_stacks sti 0: // ptr to saved state pushl %ebx call _unix_syscall // call from user mode never returns // call from kernel mode always returns (error) movl %ebx,%esp RETURN LEAF(_dbf_handler_, 0) 0: call _dbf_handler jmp 0b /* * Return directly to * a *user* context * using a specific return * frame. Typically, the * frame is in the thread * save area, but it can * also be somewhere on the * kernel stack. N.B. If the * resumed context is executing * in kernel mode, the system * will crash and burn. */ LEAF(__return_with_state, 0) // discard return address popl %eax // retrieve state ptr popl %ebx // switch stack back to save area // need to do this atomically cli movl %ebx,%esp movl $1,_empty_stacks sti RETURN /* * Perform a coroutine * switch between threads. */ LEAF(__switch_tss, 0) movl 4(%esp),%eax andl %eax,%eax je 0f movl %edi,0x44(%eax) movl %esi,0x40(%eax) movl %ebx,0x34(%eax) movl %ebp,0x3c(%eax) popl %edx movl %edx,0x20(%eax) movl %esp,0x38(%eax) movl 4(%esp),%edx movl 0x44(%edx),%edi movl 0x40(%edx),%esi movl 0x34(%edx),%ebx movl 0x3c(%edx),%ebp movl 8(%esp),%eax movl 0x38(%edx),%esp movl 0x20(%edx),%edx jmp *%edx 0: popl %edx movl 4(%esp),%edx movl 0x44(%edx),%edi movl 0x40(%edx),%esi movl 0x34(%edx),%ebx movl 0x3c(%edx),%ebp movl 8(%esp),%eax movl 0x38(%edx),%esp movl 0x20(%edx),%edx jmp *%edx LEAF(__stack_attach, 0) pushl %eax call *%ebx 0: hlt jmp 0b LEAF(__call_with_stack, 0) movl 4(%esp),%eax movl 8(%esp),%esp movl %esp,%ebp call *%eax 0: hlt jmp 0b #ifdef GPROF LEAF(mcount, 0) movl 0(%esp),%eax // fetch self address pushl %eax movl 4(%ebp),%eax // fetch parent address pushl %eax pushf popl %eax andl $0x200,%eax je 0f cli call _mcount sti addl $8,%esp ret 0: call _mcount addl $8,%esp ret #endif GPROF #define O_EDI 0 #define O_ESI 4 #define O_EBX 8 #define O_EBP 12 #define O_ESP 16 #define O_EIP 20 #define O_IPL 24 LEAF(_setjmp, 0) X_LEAF(_set_label, _setjmp) call _curipl movl 4(%esp),%edx // address of save area movl %eax,O_IPL(%edx) // save ipl level for longjmp movl %edi,O_EDI(%edx) movl %esi,O_ESI(%edx) movl %ebx,O_EBX(%edx) movl %ebp,O_EBP(%edx) movl %esp,O_ESP(%edx) movl 0(%esp),%eax // %eip (return address) movl %eax,O_EIP(%edx) xorl %eax,%eax // retval <- 0 ret LEAF(_longjmp, 0) X_LEAF(_jump_label, _longjmp) movl 4(%esp),%edx // address of save area movl O_EDI(%edx),%edi movl O_ESI(%edx),%esi movl O_EBX(%edx),%ebx movl O_EBP(%edx),%ebp movl O_ESP(%edx),%esp movl O_EIP(%edx),%eax // %eip (return address) movl %eax,0(%esp) pushl O_IPL(%edx) call _splx // restore ipl level addl $4,%esp movl $1,%eax ret
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.