:: commit 2fd36507a1fca02d26e8bf5af2d6373d07ca4902

mintsuki <mintsuki@protonmail.com> — 2020-04-25 18:33

parents: 8ef1e28e9d

Rewrite pit_sleep_and_quit_on_keypress() to be fully in real mode to avoid issues with switching back and forth

diff --git a/Makefile b/Makefile
index 50eeea3e..d6c4687b 100644
--- a/Makefile
+++ b/Makefile
@@ -17,7 +17,7 @@ echfs-test: all
 	echfs-utils -g -p1 test.img import test/test.elf boot/test.elf
 	echfs-utils -g -p1 test.img import test/qloader2.cfg qloader2.cfg
 	./qloader2-install src/qloader2.bin test.img 2048
-	qemu-system-x86_64 -hda test.img -monitor stdio
+	qemu-system-x86_64 -hda test.img -debugcon stdio
 
 ext2-test: all
 	$(MAKE) -C test
@@ -38,4 +38,4 @@ ext2-test: all
 	sudo losetup -d `cat loopback_dev`
 	rm -rf test_image loopback_dev
 	./qloader2-install src/qloader2.bin test.img 2048
-	qemu-system-x86_64 -hda test.img -monitor stdio
+	qemu-system-x86_64 -hda test.img -debugcon stdio
diff --git a/qloader2.bin b/qloader2.bin
index 1b199b80..8f1acdcb 100644
Binary files a/qloader2.bin and b/qloader2.bin differ
diff --git a/src/lib/blib.c b/src/lib/blib.c
index 98ef8138..7c8d44f5 100644
--- a/src/lib/blib.c
+++ b/src/lib/blib.c
@@ -5,7 +5,6 @@
 #include <lib/libc.h>
 #include <drivers/vga_textmode.h>
 #include <lib/real.h>
-#include <sys/interrupt.h>
 #include <lib/cio.h>
 
 void panic(const char *str) {
@@ -50,26 +49,113 @@ void *balloc_aligned(size_t count, size_t alignment) {
     return ret;
 }
 
-void pit_sleep(uint64_t pit_ticks) {
-    uint64_t target = global_pit_tick + pit_ticks;
-    while (global_pit_tick < target) {
-        asm volatile ("hlt");
-    }
+__attribute__((used)) static uint32_t int_1c_ticks_counter;
+
+__attribute__((used)) __attribute__((naked)) static void ivt_timer_isr(void) {
+    asm (
+        ".code16\n\t"
+        "pushf\n\t"
+        "push bx\n\t"
+        "mov ebx, dword ptr ds:[1f]\n\t"
+        "inc dword ptr ds:[ebx]\n\t"
+        "pop bx\n\t"
+        "popf\n\t"
+        "iret\n\t"
+        ".code32\n\t"
+        "1: .long int_1c_ticks_counter\n\t"
+    );
 }
 
-int pit_sleep_and_quit_on_keypress(uint64_t pit_ticks) {
-    uint64_t target = global_pit_tick + pit_ticks;
-    while (global_pit_tick < target) {
-        struct rm_regs r = {0};
-        r.eax = 0x0100;
-        rm_int(0x16, &r, &r);
-        if (!(r.eflags & EFLAGS_ZF)) {
-            r.eax = 0x0000;
-            rm_int(0x16, &r, &r);
-            return 1;
-        }
-    }
-    return 0;
+// This is a dirty hack but we need to execute this full function in real mode
+__attribute__((naked)) int pit_sleep_and_quit_on_keypress(uint32_t ticks) {
+    asm (
+        // pit_ticks in edx
+        "mov edx, dword ptr ss:[esp+4]\n\t"
+
+        "lea ecx, int_1c_ticks_counter\n\t"
+
+        // Make sure the ISR for int 0x1c is hooked
+        "lea eax, ivt_timer_isr\n\t"
+        "mov word ptr ds:[0x1c * 4], ax\n\t"
+        "mov word ptr ds:[0x1c * 4 + 2], 0\n\t"
+
+        "mov dword ptr ds:[ecx], 0\n\t"
+
+        // Save non-scratch GPRs
+        "push ebx\n\t"
+        "push esi\n\t"
+        "push edi\n\t"
+        "push ebp\n\t"
+
+        // Jump to real mode
+        "jmp 0x08:1f\n\t"
+        "1: .code16\n\t"
+        "mov ax, 0x10\n\t"
+        "mov ds, ax\n\t"
+        "mov es, ax\n\t"
+        "mov fs, ax\n\t"
+        "mov gs, ax\n\t"
+        "mov ss, ax\n\t"
+        "mov eax, cr0\n\t"
+        "and al, 0xfe\n\t"
+        "mov cr0, eax\n\t"
+        "jmp 0:2f\n\t"
+        "2:\n\t"
+        "mov ax, 0\n\t"
+        "mov ds, ax\n\t"
+        "mov es, ax\n\t"
+        "mov fs, ax\n\t"
+        "mov gs, ax\n\t"
+        "mov ss, ax\n\t"
+
+        "sti\n\t"
+
+        "10:\n\t"
+
+        "cmp dword ptr ds:[ecx], edx\n\t"
+        "je 30f\n\t" // out on timeout
+
+        "mov ah, 0x01\n\t"
+        "xor al, al\n\t"
+        "int 0x16\n\t"
+
+        "jz 10b\n\t" // loop
+
+        // on keypress
+        "xor ax, ax\n\t"
+        "int 0x16\n\t"
+        "mov eax, 1\n\t"
+        "jmp 20f\n\t"  // out
+
+        "30:\n\t"   // out on timeout
+        "xor eax, eax\n\t"
+
+        "20:\n\t"
+
+        "cli\n\t"
+
+        // Jump back to pmode
+        "mov ebx, cr0\n\t"
+        "or bl, 1\n\t"
+        "mov cr0, ebx\n\t"
+        "jmp 0x18:4f\n\t"
+        "4: .code32\n\t"
+        "mov bx, 0x20\n\t"
+        "mov ds, bx\n\t"
+        "mov es, bx\n\t"
+        "mov fs, bx\n\t"
+        "mov gs, bx\n\t"
+        "mov ss, bx\n\t"
+
+        // Restore non-scratch GPRs
+        "pop ebp\n\t"
+        "pop edi\n\t"
+        "pop esi\n\t"
+        "pop ebx\n\t"
+
+        // Exit
+        "ret\n\t"
+    );
 }
 
 uint64_t strtoui(const char *s) {
diff --git a/src/lib/blib.h b/src/lib/blib.h
index d2a18615..2c1b9e2e 100644
--- a/src/lib/blib.h
+++ b/src/lib/blib.h
@@ -7,7 +7,7 @@
 void panic(const char *str);
 
 void pit_sleep(uint64_t pit_ticks);
-int pit_sleep_and_quit_on_keypress(uint64_t pit_ticks);
+int pit_sleep_and_quit_on_keypress(uint32_t pit_ticks);
 
 void brewind(size_t count);
 void *balloc(size_t count);
diff --git a/src/lib/real.c b/src/lib/real.c
index 08eec87f..71c243f5 100644
--- a/src/lib/real.c
+++ b/src/lib/real.c
@@ -1,3 +1,4 @@
+#include <stdint.h>
 #include <lib/real.h>
 
 __attribute__((naked))
@@ -23,19 +24,6 @@ void rm_int(
         "push esi\n\t"
         "push edi\n\t"
         "push ebp\n\t"
-        "pushf\n\t"
-
-        "cli\n\t"
-
-        "mov dx, 0x21\n\t"
-        "mov al, byte ptr ds:[rm_pic0_mask]\n\t"
-        "out dx, al\n\t"
-        "mov dx, 0xa1\n\t"
-        "mov al, byte ptr ds:[rm_pic1_mask]\n\t"
-        "out dx, al\n\t"
-
-        "sidt [8f]\n\t"
-        "lidt [9f]\n\t"
 
         // Jump to real mode
         "jmp 0x08:1f\n\t"
@@ -106,17 +94,7 @@ void rm_int(
         "mov gs, ax\n\t"
         "mov ss, ax\n\t"
 
-        "mov dx, 0x21\n\t"
-        "mov al, byte ptr ds:[pm_pic0_mask]\n\t"
-        "out dx, al\n\t"
-        "mov dx, 0xa1\n\t"
-        "mov al, byte ptr ds:[pm_pic1_mask]\n\t"
-        "out dx, al\n\t"
-
-        "lidt [8f]\n\t"
-
         // Restore non-scratch GPRs
-        "popf\n\t"
         "pop ebp\n\t"
         "pop edi\n\t"
         "pop esi\n\t"
@@ -131,11 +109,5 @@ void rm_int(
         "6: .long 0\n\t"
         // in_regs
         "7: .long 0\n\t"
-        // pmode IDT
-        "8: .short 0\n\t"
-        "   .long  0\n\t"
-        // rmode IDT
-        "9: .short 0x3ff\n\t"
-        "   .long  0\n\t"
     );
 }
diff --git a/src/main.c b/src/main.c
index d2823d88..373cc3c2 100644
--- a/src/main.c
+++ b/src/main.c
@@ -12,7 +12,6 @@ asm (
 #include <lib/part.h>
 #include <lib/config.h>
 #include <fs/file.h>
-#include <sys/interrupt.h>
 #include <lib/elf.h>
 #include <protos/stivale.h>
 #include <protos/linux.h>
@@ -93,8 +92,6 @@ void main(int boot_drive) {
     // Initial prompt.
     init_vga_textmode();
 
-    init_idt();
-
     print("qloader2\n\n");
 
     print("Boot drive: %x\n", boot_drive);
@@ -166,7 +163,9 @@ got_entry:
         panic("KERNEL_PROTO not specified");
     }
 
-    fopen(&f, drive, part, path);
+    if (fopen(&f, drive, part, path)) {
+        panic("Could not open kernel file");
+    }
 
     if (!strcmp(proto, "stivale")) {
         stivale_load(&f, cmdline);
diff --git a/src/protos/linux.c b/src/protos/linux.c
index 41a33b0c..21e88ce7 100644
--- a/src/protos/linux.c
+++ b/src/protos/linux.c
@@ -103,15 +103,6 @@ void linux_load(struct file_handle *fd, char *cmdline) {
         "cli\n\t"
         "cld\n\t"
 
-        "mov dx, 0x21\n\t"
-        "mov al, byte ptr ds:[rm_pic0_mask]\n\t"
-        "out dx, al\n\t"
-        "mov dx, 0xa1\n\t"
-        "mov al, byte ptr ds:[rm_pic1_mask]\n\t"
-        "out dx, al\n\t"
-
-        "lidt [3f]\n\t"
-
         "jmp 0x08:1f\n\t"
         "1: .code16\n\t"
         "mov ax, 0x10\n\t"
@@ -136,10 +127,6 @@ void linux_load(struct file_handle *fd, char *cmdline) {
         "push cx\n\t"
         "push 0\n\t"
         "retf\n\t"
-
-        // rmode IDT
-        "3: .short 0x3ff\n\t"
-        "   .long  0\n\t"
         :
         : "b" (real_mode_code_seg), "c" (kernel_entry_seg)
     );
diff --git a/src/sys/interrupt.c b/src/sys/interrupt.c
deleted file mode 100644
index 3bfffaeb..00000000
--- a/src/sys/interrupt.c
+++ /dev/null
@@ -1,102 +0,0 @@
-#include <stddef.h>
-#include <stdint.h>
-#include <sys/interrupt.h>
-#include <lib/cio.h>
-#include <lib/blib.h>
-#include <lib/real.h>
-
-__attribute__((interrupt)) static void unhandled_int(void *r) {
-    (void)r;
-    panic("Unhandled interrupt");
-}
-
-volatile uint64_t global_pit_tick = 0;
-
-__attribute__((interrupt)) static void pit_irq(void *r) {
-    (void)r;
-    global_pit_tick++;
-    port_out_b(0x20, 0x20);
-}
-
-__attribute__((naked)) static void ivt_timer_isr(void) {
-    asm (
-        ".code16\n\t"
-        "pushf\n\t"
-        "push bx\n\t"
-        "mov ebx, dword ptr ds:[1f]\n\t"
-        "inc dword ptr ds:[ebx]\n\t"
-        "pop bx\n\t"
-        "popf\n\t"
-        "iret\n\t"
-        ".code32\n\t"
-        "1: .long global_pit_tick\n\t"
-    );
-}
-
-uint8_t rm_pic0_mask = 0xff;
-uint8_t rm_pic1_mask = 0xff;
-uint8_t pm_pic0_mask = 0xff;
-uint8_t pm_pic1_mask = 0xff;
-
-struct idt_entry_t {
-    uint16_t offset_lo;
-    uint16_t selector;
-    uint8_t unused;
-    uint8_t type_attr;
-    uint16_t offset_hi;
-} __attribute__((packed));
-
-struct idt_ptr_t {
-    uint16_t size;
-    uint32_t address;
-} __attribute__((packed));
-
-#define IDT_MAX_ENTRIES 16
-
-static struct idt_entry_t idt[IDT_MAX_ENTRIES];
-
-void init_idt(void) {
-    rm_pic0_mask = port_in_b(0x21);
-    rm_pic1_mask = port_in_b(0xa1);
-
-    for (int i = 0; i < IDT_MAX_ENTRIES; i++) {
-        register_interrupt_handler(i, unhandled_int, 0x8e);
-    }
-
-    register_interrupt_handler(0x08, pit_irq, 0x8e);
-
-    ivt_register_handler(0x1c, ivt_timer_isr);
-
-    struct idt_ptr_t idt_ptr = {
-        sizeof(idt) - 1,
-        (uint32_t)idt
-    };
-
-    asm volatile (
-        "lidt %0"
-        :
-        : "m" (idt_ptr)
-    );
-
-    pm_pic0_mask = 0xfe;
-    pm_pic1_mask = 0xff;
-    port_out_b(0x21, pm_pic0_mask);
-    port_out_b(0xa1, pm_pic1_mask);
-
-    asm volatile ("sti");
-}
-
-void register_interrupt_handler(size_t vec, void *handler, uint8_t type) {
-    uint32_t p = (uint32_t)handler;
-
-    idt[vec].offset_lo = (uint16_t)p;
-    idt[vec].selector = 0x18;
-    idt[vec].unused = 0;
-    idt[vec].type_attr = type;
-    idt[vec].offset_hi = (uint16_t)(p >> 16);
-}
-
-void ivt_register_handler(int vect, void *isr) {
-    volatile uint32_t *ivt = (volatile void *)0;
-    ivt[vect] = rm_seg(isr) << 16 | rm_off(isr);
-}
diff --git a/src/sys/interrupt.h b/src/sys/interrupt.h
deleted file mode 100644
index 4f33e7d1..00000000
--- a/src/sys/interrupt.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef __SYS__INTERRUPT_H__
-#define __SYS__INTERRUPT_H__
-
-#include <stdint.h>
-#include <stddef.h>
-
-extern volatile uint64_t global_pit_tick;
-
-extern uint8_t rm_pic0_mask;
-extern uint8_t rm_pic1_mask;
-extern uint8_t pm_pic0_mask;
-extern uint8_t pm_pic1_mask;
-
-void init_idt(void);
-void register_interrupt_handler(size_t, void *, uint8_t);
-void ivt_register_handler(int vect, void *isr);
-
-#endif
tab: 248 wrap: offon