kvisc/ka/sys/intr/trap0.k

216 lines
3.9 KiB
Plaintext

; The OS/K Team licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information.
TrapHandlers.prolog:
nul rbp
; rax = caller's cr1
call RFS.LoadReg, r14, $cr1
; we don't preserve the r12 we got
mov r12, rax
nul rdx
jmp rcx
TrapHandlers.epilog:
; TRAP return values: RAX-RDX
mov ax2, rax
call RFS.StoreReg, r14, $rax
mov ax2, rdx
call RFS.StoreReg, r14, $rdx
call IDT.DoneHandling, r13
iret
;
; TRAP #0 handler
;
DefaultTrapHandler:
.init:
mov rcx, .text
mov rsp, TRAP0_STACK
jmp TrapHandlers.prolog
.text:
call RFS.LoadReg, r14, $rax
call RFS.LoadArgs, r14
; will be optimized with a table
; when we have a "finished" consistent API
jraxz .handle_Shutdown
beq rax, Sys.Exit, .handle_Exit
beq rax, Sys.ExecuteInFrame, .handle_EIF
beq rax, Sys.ReadFile, .handle_ReadFile
beq rax, Sys.OpenFile, .handle_OpenFile
beq rax, Sys.CloseFile, .handle_CloseFile
beq rax, Sys.CreateFile, .handle_CreateFile
beq rax, Sys.RemoveFile, .handle_RemoveFile
beq rax, Sys.FindNext, .handle_FindNext
beq rax, Sys.FindFirst, .handle_FindFirst
beq rax, Sys.EnterHaltMode, .handle_HaltMode
.sod:
call ScreenOfDeath, .badsyscall, r13
.wrong:
call ScreenOfDeath, .badparams, r13
.fini.savecx:
mov ax2, rcx
call RFS.StoreReg, r14, $rcx
.fini:
jmp TrapHandlers.epilog
.badsyscall = "Invalid syscall number in RAX"
.badparams = "Invalid syscall parameters"
;------------------------------------------------;
; Syscall implementations ;
;------------------------------------------------;
;
; Pass control to COMMAND.COM in frame 0
;
.handle_Exit:
; deactivate current rframe
bzr r14, .hE_nz ; unless it's 0...
call RFS.DeactivateFrame, r14
.hE_nz:
; open COMMAND.COM
call DISK.OpenFile, .cmdcom
; crash on failure
bltz rax, abort
; load at CMDCOM_LOADP
mov ax1, CMDCOM_LOADP
mov ax2, CMDCOM_MAXSZ
call DISK.ReadFile, rax
; assume that COMMAND.COM being
; less then 4KB means something
; went wrong
blt rax, 0x1000, abort
; close the handle
call DISK.CloseFile, rax
; code address
mov ax2, 0x100000
call RFS.StoreReg, zero, $rip
; usermode
mov ax2, 3
call RFS.StoreReg, zero, $cr0
mov rcx, CMDCOM_LOADP
sub rcx, 0x100000
; code offset
mov ax2, rcx
call RFS.StoreReg, zero, $cr1
; return frame
nul r14
jmp .fini
.cmdcom = "command.com"
.handle_EIF:
blt ax1, 5, .wrong
; RIP can't be <1MB
mov rcx, 0x100000
blt ax0, rcx, .wrong
; add old CR1
add ax0, r12
; real RIP can't be <1MB+32KB either
; (kernel + cmdcom personal space)
add rdx, rcx, 0x8000
blt ax0, rcx, .wrong
; save rframe and compute new CR1
mov rbx, ax1
sub rdi, ax0, rcx
; activate rframe
call RFS.ActivateFrame, rbx
; save new CR1
mov ax2, rdi
call RFS.StoreReg, rbx, $cr1
; interruptible user mode
mov ax2, 3
call RFS.StoreReg, rbx, $cr0
; set RIP = 1MB
mov ax2, rcx
call RFS.StoreReg, rbx, $rip
; change return frame
mov r14, rbx
jmp .fini
;
; Disk API
;
.handle_FindFirst:
inc ax0, r12
call DISK.FindFirst
jmp .fini.savecx
.handle_FindNext:
inc ax0, r12
call DISK.FindNext
jmp .fini.savecx
.handle_OpenFile:
inc ax0, r12
call DISK.OpenFile
jmp .fini
.handle_CreateFile:
inc ax0, r12
call DISK.CreateFile
jmp .fini
.handle_RemoveFile:
inc ax0, r12
call DISK.RemoveFile
jmp .fini
.handle_CloseFile:
call DISK.CloseFile
jmp .fini
.handle_ReadFile:
inc ax1, r12
call DISK.ReadFile
jmp .fini
;
; Misc.
;
.handle_Shutdown:
call IDT.DelHandler, zero
stop
.handle_HaltMode:
pause
pause
hlt
jmp .handle_HaltMode