; desctab.asm
[BITS 32]
-%if ARCH == "i386"
-MAX_CPUS equ 1
-%else
-MAX_CPUS equ 8
-%endif
-GDT_SIZE equ (1+2*2+MAX_CPUS)*8 ; 4 Permission levels
[section .data]
-; GDT
-[global _gGDT]
-_gGDT:
- ; PL0 - Kernel
- ; PL3 - User
- dd 0x00000000, 0x00000000 ; 00 NULL Entry
- dd 0x0000FFFF, 0x00CF9A00 ; 08 PL0 Code
- dd 0x0000FFFF, 0x00CF9200 ; 10 PL0 Data
- dd 0x0000FFFF, 0x00CFFA00 ; 18 PL3 Code
- dd 0x0000FFFF, 0x00CFF200 ; 20 PL3 Data
- times MAX_CPUS dd 0, 0
-_gGDTptr:
- dw GDT_SIZE-1
- dd _gGDT
; IDT
ALIGN 8
-_gIDT:
- times 256 dd 0x00080000,0x00000F00
-_gIDTPtr:
+[global gIDT]
+gIDT:
+ ; CS = 0x08, Type = 32-bit Interrupt (0xE = 1 110)
+ times 256 dd 0x00080000,0x00000E00
+[global gIDTPtr]
+gIDTPtr:
dw 256 * 16 - 1 ; Limit
- dd _gIDT ; Base
+ dd gIDT ; Base
[section .text]
-[global _Desctab_Install]
-_Desctab_Install:
- ; Set GDT
- lgdt [_gGDTptr]
- mov ax, 0x10 ; PL0 Data
- mov ss, ax
- mov ds, ax
- mov es, ax
- mov gs, ax
- mov fs, ax
- jmp 0x08:.pl0code
-.pl0code:
- ; Set IDT
+[global Desctab_Install]
+Desctab_Install:
+ ; Set up IDT
+ ; Helper Macros
+ ; - Set an IDT entry to an ISR
%macro SETISR 1
- mov eax, _Isr%1
- mov WORD [_gIDT + %1*8], ax
+ mov eax, Isr%1
+ mov WORD [gIDT + %1*8], ax
shr eax, 16
- mov WORD [_gIDT + %1*8+6], ax
- mov ax, WORD [_gIDT + %1*8 + 4]
+ mov WORD [gIDT + %1*8+6], ax
+ ; Enable
+ mov ax, WORD [gIDT + %1*8 + 4]
or ax, 0x8000
- mov WORD [_gIDT + %1*8 + 4], ax
+ mov WORD [gIDT + %1*8 + 4], ax
+%endmacro
+ ; Enable user calling of an ISR
+%macro SET_USER 1
+ or WORD [gIDT + %1*8 + 4], 0x6000
%endmacro
-%macro SETUSER 1
- mov ax, WORD [_gIDT + %1*8 + 4]
- or ax, 0x6000
- mov WORD [_gIDT + %1*8 + 4], ax
+ ; Set an ISR as a trap (leaves interrupts enabled when invoked)
+%macro SET_TRAP 1
+ or WORD [gIDT + %1*8 + 4], 0x0100
%endmacro
+
+ ; Error handlers
%assign i 0
%rep 32
SETISR i
%assign i i+1
%endrep
+ ; User Syscall
SETISR 0xAC
- SETUSER 0xAC
+ SET_USER 0xAC
+ SET_TRAP 0xAC ; Interruptable
+ ; MP ISRs
+ %if USE_MP
+ SETISR 0xED ; 0xED Inter-processor HALT
+ SETISR 0xEE ; 0xEE Timer
+ SETISR 0xEF ; 0xEF Spurious Interrupt
+ %endif
+
+ ; IRQs
%assign i 0xF0
%rep 16
SETISR i
%endrep
; Load IDT
- lidt [_gIDTPtr]
+ lidt [gIDTPtr]
; Remap PIC
push edx ; Save EDX
mov dx, 0x20
mov al, 0x11
out dx, al ; Init Command
- mov dx, 0x21
+ mov dx, 0x21
mov al, 0xF0
out dx, al ; Offset (Start of IDT Range)
- mov al, 0x04
+ mov al, 0x04
out dx, al ; IRQ connected to Slave (00000100b) = IRQ2
- mov al, 0x01
+ mov al, 0x01
out dx, al ; Set Mode
- mov al, 0x00
+ mov al, 0x00
out dx, al ; Set Mode
mov dx, 0xA0
mov al, 0x11
out dx, al ; Init Command
- mov dx, 0xA1
+ mov dx, 0xA1
mov al, 0xF8
out dx, al ; Offset (Start of IDT Range)
- mov al, 0x02
+ mov al, 0x02
out dx, al ; IRQ Line connected to master
- mov al, 0x01
+ mov al, 0x01
out dx, al ; Set Mode
- mov dl, 0x00
+ mov dl, 0x00
out dx, al ; Set Mode
pop edx
; = Define ISRs =
; ===============
%macro ISR_ERRNO 1
-[global _Isr%1]
-_Isr%1:
+[global Isr%1]
+Isr%1:
;xchg bx, bx
push %1
jmp ErrorCommon
%endmacro
%macro ISR_NOERR 1
-[global _Isr%1]
-_Isr%1:
- xchg bx, bx
+[global Isr%1]
+Isr%1:
+ ;xchg bx, bx
push 0
push %1
jmp ErrorCommon
%endmacro
%macro DEF_SYSCALL 1
-[global _Isr%1]
-_Isr%1:
+[global Isr%1]
+Isr%1:
push 0
push %1
jmp SyscallCommon
%endmacro
%macro DEF_IRQ 1
-[global _Isr%1]
-_Isr%1:
- ;cli ; HACK!
+[global Isr%1]
+Isr%1:
push 0
push %1
jmp IRQCommon
DEF_SYSCALL 0xAC ; Acess System Call
+%if USE_MP
+[global Isr0xED]
+; 0xED - Interprocessor HALT
+Isr0xED:
+ cli
+.jmp: hlt
+ jmp .jmp
+
+[global Isr0xEE]
+[extern SchedulerBase]
+; AP's Timer Interrupt
+Isr0xEE:
+ push eax ; Line up with interrupt number
+ mov eax, dr1 ; CPU Number
+ push eax
+ mov eax, [esp+4] ; Load EAX back
+ jmp SchedulerBase
+; Spurious Interrupt
+[global Isr0xEF]
+Isr0xEF:
+ xchg bx, bx ; MAGIC BREAK
+ iret
+%endif
+
; IRQs
; - Timer
-[global _Isr240]
-_Isr240:
- push 0
+[global Isr240]
+[global Isr240.jmp]
+[extern SchedulerBase]
+[extern SetAPICTimerCount]
+Isr240:
+ push 0 ; Line up with Argument in errors
+ push 0 ; CPU Number
+ ;xchg bx, bx ; MAGIC BREAK
+Isr240.jmp:
+ %if USE_MP
+ jmp SetAPICTimerCount ; This is reset once the bus speed has been calculated
+ %else
jmp SchedulerBase
+ %endif
; - Assignable
%assign i 0xF1
%rep 16
; ---------------------
; Common error handling
; ---------------------
-[extern _ErrorHandler]
+[extern ErrorHandler]
ErrorCommon:
+ ;xchg bx, bx ; MAGIC BREAK
+
pusha
push ds
push es
push fs
push gs
+
+ ; Clear TF
+; pushf
+; and WORD [esp], 0xFEFF
+; popf
+
+ mov ax, 0x10
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
push esp
- call _ErrorHandler
+ call ErrorHandler
add esp, 4
pop gs
; --------------------------
; Common System Call Handler
; --------------------------
-[extern _SyscallHandler]
+[extern SyscallHandler]
SyscallCommon:
pusha
push ds
push gs
push esp
- call _SyscallHandler
+ call SyscallHandler
add esp, 4
+ ; Pass changes to TF on to the user
+ ; EFLAGS is stored at ESP[4+8+2+2]
+ ; 4 Segment Registers
+ ; 8 GPRs
+ ; 2 Error Code / Interrupt ID
+ ; 2 CS/EIP
+ pushf
+ pop eax
+ and eax, 0x100 ; 0x100 = Trace Flag
+ and WORD [esp+(4+8+2+2)*4], ~0x100 ; Clear
+ or DWORD [esp+(4+8+2+2)*4], eax ; Set for user
+
pop gs
pop fs
pop es
; ------------
; IRQ Handling
; ------------
-[extern _IRQ_Handler]
+[extern IRQ_Handler]
+[global IRQCommon]
+[global IRQCommon_handled]
+IRQCommon_handled equ IRQCommon.handled
IRQCommon:
pusha
push ds
push fs
push gs
+ mov ax, 0x10
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+
push esp
- call _IRQ_Handler
+ call IRQ_Handler
+.handled:
add esp, 4
pop gs
add esp, 8 ; Error Code and ID
iret
-; --------------
-; Task Scheduler
-; --------------
-[extern _Proc_Scheduler]
-SchedulerBase:
- pusha
- push ds
- push es
- push fs
- push gs
-
- mov eax, [esp+12*4] ; CPU Number
- push eax ; Pus as argument
-
- call _Proc_Scheduler
-
- add esp, 4 ; Remove Argument
-
- pop gs
- pop fs
- pop es
- pop ds
-
- mov dx, 0x20
- mov al, 0x20
- out dx, al ; ACK IRQ
- popa
- add esp, 4 ; CPU ID
- ; No Error code / int num
- iret
+; vim: ft=nasm ts=8