www.pudn.com > COS0.0.1.rar > int.s
; int.s - low-level interrupt routines ; ; Author: Paul Barker ; Part of: COS ; Created: 15/04/04 ; Last Modified: 04/10/04 ; ; Copyright (C) 2004 Paul Barker ; ; 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. ; ; This program 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 General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program; if not, write to the Free Software ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; ; (See file "Copying") ; See "COPYING-GEEKOS" about the code here that is taken from GeekOS [BITS 32] ; include this for KERNEL_CS %include "defs.inc" GLOBAL lgdtr GLOBAL lidtr ; Sizes of interrupt handler entry points for interrupts with ; and without error codes. The code in idt.c uses this ; information to infer the layout of the table of interrupt ; handler entry points, without needing a separate linker ; symbol for each one (which is quite tedious to type :-) GLOBAL g_handlerSizeNoErr GLOBAL g_handlerSizeErr ; Beginning and end of the table of interrupt entry points. GLOBAL g_entryPointTableStart GLOBAL g_entryPointTableEnd ; get interrupts tbl from sysinfo->interrupts EXTERN sysinfo ; fake return address to setup a thread GLOBAL FakeReturnAddr ; ---------------------------------------------------------------------- ; Interrupt Definitions ; - We are using the GeekOS way of handling interrupts, ; most of this code is taken from GeekOS ; ---------------------------------------------------------------------- ; This is the size of the Interrupt_State struct in int.h INTERRUPT_STATE_SIZE equ 64 ; Save registers prior to calling a handler function. ; This must be kept up to date with: ; - Interrupt_State struct in int.h %macro Save_Registers 0 push eax push ebx push ecx push edx push esi push edi push ebp push ds push es push fs push gs %endmacro ; Restore registers and clean up the stack after calling a handler function ; (i.e., just before we return from the interrupt via an iret instruction). %macro Restore_Registers 0 pop gs pop fs pop es pop ds pop ebp pop edi pop esi pop edx pop ecx pop ebx pop eax add esp, 8 ; skip int num and error code %endmacro ; Number of bytes between the top of the stack and ; the interrupt number after the general-purpose and segment ; registers have been saved. REG_SKIP equ (11*4) ; Template for entry point code for interrupts that have ; an explicit processor-generated error code. ; The argument is the interrupt number. %macro Int_With_Err 1 align 8 push dword %1 ; push interrupt number jmp Handle_Interrupt ; jump to common handler %endmacro ; Template for entry point code for interrupts that do not ; generate an explicit error code. We push a dummy error ; code on the stack, so the stack layout is the same ; for all interrupts. %macro Int_No_Err 1 align 8 push dword 0 ; fake error code push dword %1 ; push interrupt number jmp Handle_Interrupt ; jump to common handler %endmacro ; ---------------------------------------------------------------------- ; Code ; ---------------------------------------------------------------------- [SECTION .text] ; Load IDTR with 6-byte pointer whose address is passed as ; the parameter. Taken from GeekOS, like so much else... align 8 lidtr: mov eax, [esp+4] lidt [eax] ret ; Load GDTR with 6-byte pointer whose address is passed as ; the parameter. This really belongs somewhere else, but for ; now it is here. align 8 lgdtr: mov eax, [esp+4] lgdt [eax] mov ax, KERNEL_DS mov ds, ax mov es, ax mov fs, ax mov gs, ax ; now do a far jump to reload everything jmp KERNEL_CS:.here .here: ret ; Common interrupt handling code. ; Save registers, call C handler function, ; possibly choose a new thread to run, restore ; registers, return from the interrupt. align 8 Handle_Interrupt: ; Save registers (general purpose and segment) Save_Registers ; Ensure that we're using the kernel data segment mov ax, KERNEL_DS mov ds, ax mov es, ax ; Get the address of the C handler function from the ; table of handler functions. mov eax, [sysinfo] ; sysinfo mov eax, [eax] ; sysinfo->interrupts add eax, 2048 ; interrupts is first entry of sysinfo, ; and handler table is 2k into interrupts mov esi, [esp+REG_SKIP] ; get interrupt number mov ebx, [eax+esi*4] ; get address of handler function ; Call the handler. ; The argument passed is a pointer to an Interrupt_State struct, ; which describes the stack layout for all interrupts. push esp call ebx FakeReturnAddr: add esp, 4 ; clear 1 argument ; Restore registers Restore_Registers ; Return from the interrupt. iret ; ---------------------------------------------------------------------- ; Generate interrupt-specific entry points for all interrupts. ; We also define symbols to indicate the extend of the table ; of entry points, and the size of individual entry points. ; ---------------------------------------------------------------------- align 8 g_entryPointTableStart: ; Handlers for processor-generated exceptions, as defined by ; Intel 486 manual. Int_No_Err 0 align 8 Before_No_Err: Int_No_Err 1 align 8 After_No_Err: Int_No_Err 2 ; Described in my Intel manual as NMI ; an int 2 instruction does not do a 'real' NMI Int_No_Err 3 Int_No_Err 4 Int_No_Err 5 Int_No_Err 6 Int_No_Err 7 align 8 Before_Err: Int_With_Err 8 align 8 After_Err: Int_No_Err 9 ; Described as Coprocessor segment overrun. Apparantly ; recent IA-32 processors should NOT generate this exception Int_With_Err 10 Int_With_Err 11 Int_With_Err 12 Int_With_Err 13 Int_With_Err 14 Int_No_Err 15 ; RESERVED Int_No_Err 16 Int_With_Err 17 ; The remaining interrupts (18 - 255) do not have error codes. ; We can generate them all in one go with nasm's %rep construct. %assign intNum 18 %rep (256 - 18) Int_No_Err intNum %assign intNum intNum+1 %endrep align 8 g_entryPointTableEnd: [SECTION .rodata] ; Exported symbols defining the size of handler entry points ; (both with and without error codes). align 4 g_handlerSizeNoErr: dd (After_No_Err - Before_No_Err) align 4 g_handlerSizeErr: dd (After_Err - Before_Err)