From 59fbf66cfe9668af24fe525f4facf880540f6eb2 Mon Sep 17 00:00:00 2001 From: julianb0 Date: Tue, 6 Aug 2019 22:47:39 +0200 Subject: [PATCH] death_screen --- as/k-as.py | 21 +++---- as/regs.lst | 64 +++++++++++----------- ka/crt/crt.k | 1 + ka/crt/fmt/ltostr.k | 3 +- ka/doskrnl.k | 3 + ka/sys/dumprf.k | 127 +++++++++++++++++++++++++++++++++++++++++++ ka/sys/intr/common.k | 58 +++++++++++++++++++- ka/sys/intr/trap0.k | 6 +- ka/usr/cmd/main.k | 10 ++++ vm/in/MISC | 5 ++ vm/in/misc.c | 21 ++++++- vm/pc/keybd.c | 8 +++ vm/pc/keybd.h | 2 + 13 files changed, 279 insertions(+), 50 deletions(-) create mode 100644 ka/sys/dumprf.k diff --git a/as/k-as.py b/as/k-as.py index 7b3b2ac..f6d0da1 100755 --- a/as/k-as.py +++ b/as/k-as.py @@ -631,28 +631,29 @@ def parse_instr(line): if imm1 == '1': # [reg+reg] if imm2 == '0': - instr_args += "%%imm8 {} {} {}".format(fmts["m_rr"]|mlen, reg1, reg2) + instr_args += "%%imm8 {} {} {}".format(fmts["m_rr"]|mlen, '$'+reg1, '$'+reg2) size += 3 # [reg+reg+imm] else: - instr_args += "%%imm8 {} {} {} %%signed %%imm16 {}".format(fmts["m_rriw"]|mlen, reg1, reg2, imm2) + instr_args += "%%imm8 {} {} {} %%signed %%imm16 {}"\ + .format(fmts["m_rriw"]|mlen, '$'+reg1, '$'+reg2, imm2) size += 5 # [reg+reg*imm+imm] else: instr_args += "%%imm8 {} {} {} %%imm8 {} %%signed %%imm32 {}"\ - .format(fmts["m_rrii"]|mlen, reg1, reg2, imm1, imm2) + .format(fmts["m_rrii"]|mlen, '$'+reg1, '$'+reg2, imm1, imm2) size += 8 # [reg] - elif word in pregs: - instr_args += "%%imm8 {} {}".format(fmts["m_r"]|mlen, word) + elif '$'+word in pregs: + instr_args += "%%imm8 {} {}".format(fmts["m_r"]|mlen, '$'+word) size += 2 # [imm], converted to [zero+imm] else: - instr_args += "%%imm8 {} zero zero %%signed %%imm32 {}".format(fmts["m_rrid"]|mlen, word) + instr_args += "%%imm8 {} $zero $zero %%signed %%imm32 {}".format(fmts["m_rrid"]|mlen, word) size += 7 continue @@ -669,8 +670,8 @@ def parse_instr(line): # register index $reg if len(word) == 4 and word[0] == '$': - if word[1:] in pregs: - word = str(pregs[word[1:]]) + if '$'+word[1:] in pregs: + word = str(pregs['$'+word[1:]]) # fallthrough # immediates @@ -700,9 +701,9 @@ def parse_instr(line): continue # register - elif word in pregs: + elif '$'+word in pregs: size += 1 - instr_args += word + instr_args += '$'+word continue # it's a label (a 32-bit immediate) diff --git a/as/regs.lst b/as/regs.lst index 7068124..74376a0 100644 --- a/as/regs.lst +++ b/as/regs.lst @@ -1,34 +1,34 @@ -rzx zr zero -cr0 c0 -cr1 c1 -cr2 c2 -rfx fx -rip ip -rbp bp -rsp sp +$rzx $zero +$cr0 +$cr1 +$cr2 +$rfx +$rip +$rbp +$rsp -rax ax r0 -rbx bx r1 -rcx cx r2 -rdx dx r3 -rsi si r4 -rdi di r5 -ax0 a0 r6 -ax1 a1 r7 -ax2 a2 r8 -ax3 a3 r9 -ax4 a4 r10 -ax5 a5 r11 +$rax $r0 +$rbx $r1 +$rcx $r2 +$rdx $r3 +$rsi $r4 +$rdi $r5 +$ax0 $r6 +$ax1 $r7 +$ax2 $r8 +$ax3 $r9 +$ax4 $r10 +$ax5 $r11 -nx0 n0 r12 -nx1 n1 r13 -nx2 n2 r14 -nx3 n3 r15 -nx4 n4 r16 -nx5 n5 r17 -nx6 n6 r18 -nx7 n7 r19 -nx8 n8 r20 -grp gp -trp tp -srp sp +$nx0 $r12 +$nx1 $r13 +$nx2 $r14 +$nx3 $r15 +$nx4 $r16 +$nx5 $r17 +$nx6 $r18 +$nx7 $r19 +$nx8 $r20 +$grp $r21 +$trp $r22 +$srp $r22 diff --git a/ka/crt/crt.k b/ka/crt/crt.k index 3f9db23..6088c01 100644 --- a/ka/crt/crt.k +++ b/ka/crt/crt.k @@ -33,6 +33,7 @@ FNAME_MAX := 0x0000000000000080 ; PRN_CLEAR := 0x000000008BF00001 +PRN_FLUSH := 0x000000008BF00002 ; ; CRT librairies diff --git a/ka/crt/fmt/ltostr.k b/ka/crt/fmt/ltostr.k index 0763d44..8517144 100644 --- a/ka/crt/fmt/ltostr.k +++ b/ka/crt/fmt/ltostr.k @@ -20,6 +20,7 @@ utoa: ; ltostr: mov rax, ax0 + mov rcx, zero ; make sure base is in [2, 32] b.b ax2, 2, .bad @@ -60,7 +61,7 @@ ltostr: ; add minus flag, null-terminate and reverse .fini: mov.cxnz b[ax0], '-' - add.cxnz ax0, ax0, 1 + inc.cxnz ax0, 1 mov b[ax0], zero diff --git a/ka/doskrnl.k b/ka/doskrnl.k index c855a0e..1a039d4 100644 --- a/ka/doskrnl.k +++ b/ka/doskrnl.k @@ -26,6 +26,8 @@ start: mov rsp, DOSKRNL_STACK mov rbp, zero + ;dump + call main crash @@ -42,4 +44,5 @@ include "sys/intr/common.k" include "sys/intr/trap0.k" include "sys/main.k" +include "sys/dumprf.k" diff --git a/ka/sys/dumprf.k b/ka/sys/dumprf.k new file mode 100644 index 0000000..af68f66 --- /dev/null +++ b/ka/sys/dumprf.k @@ -0,0 +1,127 @@ +; The OS/K Team licenses this file to you under the MIT license. +; See the LICENSE file in the project root for more information. + +dumprf: + push rbp + mov rbp, rsp + + push r12 + mov r12, ax0 + + call RFS.LoadReg, r12, $cr2 + push rax + + call RFS.LoadReg, r12, $cr1 + push rax + + call RFS.LoadReg, r12, $cr0 + push rax + + call RFS.LoadReg, r12, $rfx + push rax + + call RFS.LoadReg, r12, $rip + push rax + + push r12 + call printf, .dmp1 + + call RFS.LoadReg, r12, $srp + push rax + + call RFS.LoadReg, r12, $trp + push rax + + push 0 # fixme + + call RFS.LoadReg, r12, $rbp + push rax + + call RFS.LoadReg, r12, $rsp + push rax + + call printf, .dmp2 + + call RFS.LoadReg, r12, $ax5 + push rax + + call RFS.LoadReg, r12, $ax4 + push rax + + call RFS.LoadReg, r12, $ax3 + push rax + + call RFS.LoadReg, r12, $ax2 + push rax + + call RFS.LoadReg, r12, $ax1 + push rax + + call RFS.LoadReg, r12, $ax0 + push rax + + call printf, .dmp3 + + call RFS.LoadReg, r12, $rdi + push rax + + call RFS.LoadReg, r12, $rsi + push rax + + call RFS.LoadReg, r12, $rdx + push rax + + call RFS.LoadReg, r12, $rcx + push rax + + call RFS.LoadReg, r12, $rbx + push rax + + call RFS.LoadReg, r12, $rax + push rax + + call printf, .dmp4 + + call RFS.LoadReg, r12, $r17 + push rax + + call RFS.LoadReg, r12, $r16 + push rax + + call RFS.LoadReg, r12, $r15 + push rax + + call RFS.LoadReg, r12, $r14 + push rax + + call RFS.LoadReg, r12, $r13 + push rax + + call RFS.LoadReg, r12, $r12 + push rax + + call printf, .dmp5 + + call RFS.LoadReg, r12, $r20 + push rax + + call RFS.LoadReg, r12, $r19 + push rax + + call RFS.LoadReg, r12, $r18 + push rax + + call printf, .dmp6 + + pop r12 + + leave + ret + +.dmp1 = "Environ #1:\nfrm=0d%d rip=0x%x rfx=0x%x\ncr0=0x%x cr1=0x%x cr2=0x%x\n\n" +.dmp2 = "Environ #2:\nrsp=0x%x rbp=0x%x ind=0d%d\ngrp=0x%x trp=0x%x srp=0x%x\n\n" +.dmp3 = "Argument:\nr12=0x%x ax1=0x%x ax2=0x%x\nax3=0x%x ax4=0x%x ax5=0x%x\n\n" +.dmp4 = "Volatile:\nrax=0x%x rbx=0x%x rcx=0x%x\nrdx=0x%x rsi=0x%x rdi=0x%x\n\n" +.dmp5 = "Persistent:\nr12=0x%x r13=0x%x r14=0x%x\nr15=0x%x r16=0x%x r17=0x%x\n" +.dmp6 = "r18=0x%x r19=0x%x r20=0x%x\n" + diff --git a/ka/sys/intr/common.k b/ka/sys/intr/common.k index 28aecc1..c4ee327 100644 --- a/ka/sys/intr/common.k +++ b/ka/sys/intr/common.k @@ -4,7 +4,7 @@ TrapHandlers.prolog: mov rbp, rsp - ; nx0 = caller's cr2 + ; rax = caller's cr2 call RFS.LoadReg, r14, $cr2 ; we don't preserve the r12 we got @@ -14,7 +14,6 @@ TrapHandlers.prolog: jmp rcx TrapHandlers.epilog: - ; TRAP return values: RAX-RDX mov ax2, rax @@ -27,3 +26,58 @@ TrapHandlers.epilog: iret +ScreenOfDeath: + push r12 + mov r12, ax0 + + prn 10 + prn PRN_CLEAR + prn PRN_FLUSH + + call print, .scr1 + + b.nz r14, zero, .not_con + push .scr2_con + jmp .do_print + +.not_con: + b.l r14, 4, .not_krn + push .scr2_krn + jmp .do_print + +.not_krn: + push .scr2_usr + +.do_print: + push r14 + push r12 + call printf, .scr2 + inc rsp, 24 + + call dumprf, r14 + prn 10 + + call print, .scr3 + +.loop: + pause + pause + + scan rax + jmp.axz .loop + + b.z rax, 0x0A, trap0_handler.handle_Exit + b.z rax, 0x1B, trap0_handler.handle_Shutdown + + jmp .loop + + crash + +.scr1 = "-------- Unhandled EXCEPTION, TRAP/SYSCALL or INTERRUPT\n" +.scr2 = "Offense description: %s\nOffending frame: %d (%s)\n\n" +.scr3 = "Press:\n ENTER to procede to COMMAND.COM\n ESCAPE to shutdown machine\n\n" + +.scr2_con = "dedicated command.com frame" +.scr2_usr = "userspace application frame" +.scr2_krn = "exception/interrupt handler" + diff --git a/ka/sys/intr/trap0.k b/ka/sys/intr/trap0.k index ed8f393..cfde799 100644 --- a/ka/sys/intr/trap0.k +++ b/ka/sys/intr/trap0.k @@ -23,9 +23,7 @@ trap0_handler: b.z rax, Sys.FindFirst, .handle_FindFirst b.z rax, Sys.EnterHaltMode, .handle_HaltMode - mov rax, 1 << 63 - mov rcx, 1 << 63 - mov rdx, 1 << 63 + call ScreenOfDeath, .badsyscall .fini.savecx: mov ax2, rcx @@ -34,6 +32,8 @@ trap0_handler: .fini: jmp TrapHandlers.epilog +.badsyscall = "Invalid syscall number in RAX" + ;------------------------------------------------; ; Syscall implementations ; ;------------------------------------------------; diff --git a/ka/usr/cmd/main.k b/ka/usr/cmd/main.k index 5cf0f35..6e1dc8b 100644 --- a/ka/usr/cmd/main.k +++ b/ka/usr/cmd/main.k @@ -130,6 +130,10 @@ main: call strcmp, argv0, .builtin_cls jmp.axz .handle_CLS +.builtin_crash = "crash" + call strcmp, argv0, .builtin_crash + jmp.axz .handle_CRASH + .builtin_date = "date" call strcmp, argv0, .builtin_date jmp.axz .handle_DATE @@ -195,6 +199,12 @@ main: prn PRN_CLEAR jmp .print_prompt +.handle_CRASH: + mov rax, 0xDEADBEEF + trap 0 + + jmp .print_prompt + .handle_DATE: call GetTimeUTC diff --git a/vm/in/MISC b/vm/in/MISC index f4d3760..7b0533c 100644 --- a/vm/in/MISC +++ b/vm/in/MISC @@ -24,6 +24,11 @@ dump # Misc. instructions # #---------------------------------------------------------------------------# +# +# Throws #UDF ("undefined behaviour") +# +udf + # # Pause the CPU for a very short amount of time (PAUSE) # Used in spin-type loops diff --git a/vm/in/misc.c b/vm/in/misc.c index 3fb3255..a17ac6d 100644 --- a/vm/in/misc.c +++ b/vm/in/misc.c @@ -11,6 +11,7 @@ IMPL_START(into) { INTO(); return 0; } IMPL_START(pause) { usleep(5000); return 0; } +IMPL_START(udf) { _except(E_UDF, "UDF instruction"); } //----------------------------------------------------------------------------// @@ -123,7 +124,9 @@ IMPL_START(dswap) //----------------------------------------------------------------------------// +#define PRN_MAGIC_MASK 0x8BF00000 #define PRN_CLEAR_MAGIC 0x8BF00001 +#define PRN_FLUSH_MAGIC 0x8BF00002 IMPL_START(prn) { @@ -132,8 +135,22 @@ IMPL_START(prn) ulong v = p1->val; // Magic value? :) - if (__builtin_expect(v == PRN_CLEAR_MAGIC, 0)) - console_clear(); + if (__builtin_expect((v & PRN_MAGIC_MASK) > 0, 0)) + { + switch (v) + { + case PRN_CLEAR_MAGIC: + console_clear(); + break; + + case PRN_FLUSH_MAGIC: + console_flushkeybuf(); + break; + + default: + _except(E_ILL, "Bad PRN magic"); + } + } else if (v > 0) console_putc((char)v); diff --git a/vm/pc/keybd.c b/vm/pc/keybd.c index 5b5b27f..cc21e40 100644 --- a/vm/pc/keybd.c +++ b/vm/pc/keybd.c @@ -37,6 +37,12 @@ keycode_t console_scankeybuf(void) return 0; } +void console_flushkeybuf(void) +{ + memset(keybuf, 0, KEYBUFSIZE); + keybuf_last = keybuf_ptr = &keybuf[0]; +} + #define QKEY(key, c, cshift, cmode, calt, cgui) \ _QKEY(SDLK_##key, c, cshift, cmode, calt, cgui) @@ -70,6 +76,8 @@ void console_handle_input(SDL_Keycode key) case SDLK_SPACE: code = ' '; break; case SDLK_BACKSPACE: code = '\b'; break; + case SDLK_ESCAPE: code = 0x1B; break; + case SDLK_RETURN: case SDLK_RETURN2: code = '\n'; diff --git a/vm/pc/keybd.h b/vm/pc/keybd.h index e729538..4a554cd 100644 --- a/vm/pc/keybd.h +++ b/vm/pc/keybd.h @@ -12,6 +12,8 @@ extern keycode_t *keybuf_ptr; keycode_t console_getkey(void); keycode_t console_scankeybuf(void); +void console_flushkeybuf(void); + void console_addkey(keycode_t); void console_handle_input(SDL_Keycode key);