X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=blobdiff_plain;f=palacios%2Fsrc%2Fgeekos%2Flowlevel.asm;fp=palacios%2Fsrc%2Fgeekos%2Flowlevel.asm;h=0000000000000000000000000000000000000000;hp=63f93c262b049595d5bd2893c38cfd316513bd5f;hb=ddc16b0737cf58f7aa90a69c6652cdf4090aec51;hpb=626595465a2c6987606a6bc697df65130ad8c2d3 diff --git a/palacios/src/geekos/lowlevel.asm b/palacios/src/geekos/lowlevel.asm deleted file mode 100644 index 63f93c2..0000000 --- a/palacios/src/geekos/lowlevel.asm +++ /dev/null @@ -1,576 +0,0 @@ -; -*- fundamental -*- -; Low level interrupt/thread handling code for GeekOS. -; Copyright (c) 2001,2003,2004 David H. Hovemeyer -; Copyright (c) 2003, Jeffrey K. Hollingsworth -; $Revision: 1.1 $ - -; This is free software. You are permitted to use, -; redistribute, and modify it as specified in the file "COPYING". - -; This is 32 bit code to be linked into the kernel. -; It defines low level interrupt handler entry points that we'll use -; to populate the IDT. It also contains the interrupt handling -; and thread context switch code. - -%include "defs.asm" -%include "symbol.asm" -%include "util.asm" - - -[BITS 32] - -; ---------------------------------------------------------------------- -; Definitions -; ---------------------------------------------------------------------- - -; 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 -; - Setup_Initial_Thread_Context() in kthread.c -%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 - -; Code to activate a new user context (if necessary), before returning -; to executing a thread. Should be called just before restoring -; registers (because the interrupt context is used). -%macro Activate_User_Context 0 - ; If the new thread has a user context which is not the current - ; one, activate it. - push esp ; Interrupt_State pointer - push dword [g_currentThread] ; Kernel_Thread pointer -; call Switch_To_User_Context - add esp, 8 ; clear 2 arguments -%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 - - -; ---------------------------------------------------------------------- -; Symbol imports and exports -; ---------------------------------------------------------------------- - -; This symbol is defined in idt.c, and is a table of addresses -; of C handler functions for interrupts. -IMPORT g_interruptTable - -; Global variable pointing to context struct for current thread. -IMPORT g_currentThread - -; Set to non-zero when we need to choose a new thread -; in the interrupt return code. -IMPORT g_needReschedule - -; Set to non-zero when preemption is disabled. -IMPORT g_preemptionDisabled - -; This is the function that returns the next runnable thread. -IMPORT Get_Next_Runnable - -; Function to put a thread on the run queue. -IMPORT Make_Runnable - -; Function to activate a new user context (if needed). -IMPORT Switch_To_User_Context - -; 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 :-) -EXPORT g_handlerSizeNoErr -EXPORT g_handlerSizeErr - -; Simple functions to load the IDTR, GDTR, and LDTR. -EXPORT Load_IDTR -EXPORT Load_GDTR -EXPORT Load_LDTR - -; Beginning and end of the table of interrupt entry points. -EXPORT g_entryPointTableStart -EXPORT g_entryPointTableEnd - -; Thread context switch function. -EXPORT Switch_To_Thread - -; Return current value of eflags register. -EXPORT Get_Current_EFLAGS - -; Return the return address -EXPORT Get_EIP -; ESP -EXPORT Get_ESP -; EBP -EXPORT Get_EBP - -; Virtual memory support. -EXPORT Enable_Paging -EXPORT Set_PDBR -EXPORT Get_PDBR -EXPORT Flush_TLB - -; CPUID functions -EXPORT cpuid_ecx -EXPORT cpuid_eax - -; Utility Functions -EXPORT Set_MSR -EXPORT Get_MSR - -EXPORT Get_CR2 - - -EXPORT Proc_test - -; ---------------------------------------------------------------------- -; Code -; ---------------------------------------------------------------------- - -[SECTION .text] - -; Load IDTR with 6-byte pointer whose address is passed as -; the parameter. -align 8 -Load_IDTR: - mov eax, [esp+4] - lidt [eax] - ret - -; Load the GDTR with 6-byte pointer whose address is -; passed as the parameter. Assumes that interrupts -; are disabled. -align 8 -Load_GDTR: - mov eax, [esp+4] - lgdt [eax] - ; Reload segment registers - mov ax, KERNEL_DS - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax - mov ss, ax - jmp KERNEL_CS:.here -.here: - ret - -; Load the LDT whose selector is passed as a parameter. -align 8 -Load_LDTR: - mov eax, [esp+4] - lldt ax - ret - -; -; Start paging -; load crt3 with the passed page directory pointer -; enable paging bit in cr2 -align 8 -Enable_Paging: - push ebp - mov ebp, esp - push eax - push ebx - mov eax, [ebp+8] - mov cr3, eax - mov eax, cr3 - mov cr3, eax - mov ebx, cr0 - or ebx, 0x80000000 - mov cr0, ebx - pop ebx - pop eax - pop ebp - ret - - - - - -; -; Change PDBR -; load cr3 with the passed page directory pointer -align 8 -Set_PDBR: - mov eax, [esp+4] - mov cr3, eax - ret - -; -; Get the current PDBR. -; This is useful for lazily switching address spaces; -; only switch if the new thread has a different address space. -; -align 8 -Get_PDBR: - mov eax, cr3 - ret - -; -; Flush TLB - just need to re-load cr3 to force this to happen -; -align 8 -Flush_TLB: - mov eax, cr3 - mov cr3, eax - ret - - -; -; cpuid_ecx - return the ecx register from cpuid -; -align 8 -cpuid_ecx: - push ebp - mov ebp, esp - push ecx - mov eax, [ebp + 8] - cpuid - mov eax, ecx - pop ecx - pop ebp - ret - -; -; cpuid_eax - return the eax register from cpuid -; -align 8 -cpuid_eax: - mov eax, [esp+4] - cpuid - ret - -; -; Set_MSR - Set the value of a given MSR -; -align 8 -Set_MSR: - push ebp - mov ebp, esp - pusha - mov eax, [ebp+16] - mov edx, [ebp+12] - mov ecx, [ebp+8] - wrmsr - popa - pop ebp - ret - - - -; -; Get_MSR - Get the value of a given MSR -; void Get_MSR(int MSR, void * high_byte, void * low_byte); -; -align 8 -Get_MSR: - push ebp - mov ebp, esp - pusha - mov ecx, [ebp+8] - rdmsr - mov ebx, [ebp+12] - mov [ebx], edx - mov ebx, [ebp+16] - mov [ebx], eax - popa - pop ebp - ret - - - -align 8 -Get_CR2: - mov eax, cr2 - ret - - -align 8 -Proc_test: - push ebp - mov ebp, esp - push ebx - mov ebx, [ebp + 8] - mov eax, [ebp + 12] - - add eax, ebx - pop ebx - pop ebp - 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, g_interruptTable ; get address of handler table - 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 - add esp, 4 ; clear 1 argument - - ; If preemption is disabled, then the current thread - ; keeps running. - cmp [g_preemptionDisabled], dword 0 - jne .restore - - ; See if we need to choose a new thread to run. - cmp [g_needReschedule], dword 0 - je .restore - - ; Put current thread back on the run queue - push dword [g_currentThread] - call Make_Runnable - add esp, 4 ; clear 1 argument - - ; Save stack pointer in current thread context, and - ; clear numTicks field. - mov eax, [g_currentThread] - mov [eax+0], esp ; esp field - mov [eax+4], dword 0 ; numTicks field - - ; Pick a new thread to run, and switch to its stack - call Get_Next_Runnable - mov [g_currentThread], eax - mov esp, [eax+0] ; esp field - - ; Clear "need reschedule" flag - mov [g_needReschedule], dword 0 - -.restore: - ; Activate the user context, if necessary. - Activate_User_Context - - ; Restore registers - Restore_Registers - - ; Return from the interrupt. - iret - -; ---------------------------------------------------------------------- -; Switch_To_Thread() -; Save context of currently executing thread, and activate -; the thread whose context object is passed as a parameter. -; -; Parameter: -; - ptr to Kernel_Thread whose state should be restored and made active -; -; Notes: -; Called with interrupts disabled. -; This must be kept up to date with definition of Kernel_Thread -; struct, in kthread.h. -; ---------------------------------------------------------------------- -align 16 -Switch_To_Thread: - ; Modify the stack to allow a later return via an iret instruction. - ; We start with a stack that looks like this: - ; - ; thread_ptr - ; esp --> return addr - ; - ; We change it to look like this: - ; - ; thread_ptr - ; eflags - ; cs - ; esp --> return addr - - push eax ; save eax - mov eax, [esp+4] ; get return address - mov [esp-4], eax ; move return addr down 8 bytes from orig loc - add esp, 8 ; move stack ptr up - pushfd ; put eflags where return address was - mov eax, [esp-4] ; restore saved value of eax - push dword KERNEL_CS ; push cs selector - sub esp, 4 ; point stack ptr at return address - - ; Push fake error code and interrupt number - push dword 0 - push dword 0 - - ; Save general purpose registers. - Save_Registers - - ; Save stack pointer in the thread context struct (at offset 0). - mov eax, [g_currentThread] - mov [eax+0], esp - - ; Clear numTicks field in thread context, since this - ; thread is being suspended. - mov [eax+4], dword 0 - - ; Load the pointer to the new thread context into eax. - ; We skip over the Interrupt_State struct on the stack to - ; get the parameter. - mov eax, [esp+INTERRUPT_STATE_SIZE] - - ; Make the new thread current, and switch to its stack. - mov [g_currentThread], eax - mov esp, [eax+0] - - ; Activate the user context, if necessary. - Activate_User_Context - - ; Restore general purpose and segment registers, and clear interrupt - ; number and error code. - Restore_Registers - - ; We'll return to the place where the thread was - ; executing last. - iret - -; Return current contents of eflags register. -align 16 -Get_Current_EFLAGS: - pushfd ; push eflags - pop eax ; pop contents into eax - ret - - - -; Return the eip of the next instruction after the caller -align 16 -Get_EIP: - mov eax, [esp] - ret - -; Return the current esp in the procedure -align 16 -Get_ESP: - mov eax, esp - ret - -; Return the current ebp in the procedure -align 16 -Get_EBP: - mov eax, ebp - ret - - - -; ---------------------------------------------------------------------- -; 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 ; FIXME: not described in 486 manual -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 ; FIXME: not described in 486 manual -Int_With_Err 10 -Int_With_Err 11 -Int_With_Err 12 -Int_With_Err 13 -Int_With_Err 14 -Int_No_Err 15 ; FIXME: not described in 486 manual -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 .data] - -; 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)