ソースを参照

Merge branch 'syscall'

greatbridf 2 年 前
コミット
9a6aa020d8

+ 2 - 0
CMakeLists.txt

@@ -45,6 +45,7 @@ set(KERNEL_MAIN_SOURCES src/kernel_main.c
                         src/kernel/process.cpp
                         src/kernel/tty.c
                         src/kernel/stdio.c
+                        src/kernel/syscall.cpp
                         src/kernel/mem.cpp
                         src/kernel/vfs.cpp
                         src/kernel/vga.c
@@ -63,6 +64,7 @@ set(KERNEL_MAIN_SOURCES src/kernel_main.c
                         include/kernel/interrupt.h
                         include/kernel/process.hpp
                         include/kernel/stdio.h
+                        include/kernel/syscall.hpp
                         include/kernel/mem.h
                         include/kernel/mm.hpp
                         include/kernel/vfs.h

+ 10 - 2
Makefile.src

@@ -15,11 +15,15 @@ srun: build
 nativerun: build
 	$(QEMU_BIN) $(QEMU_ARGS) -display none -serial mon:stdio
 
-.PHONY: configure
-configure:
+.PHONY: prepare
+prepare:
 	cmake -Bbuild -DCMAKE_BUILD_TYPE=Debug $(CROSS_COMPILE)
 	cp build/compile_commands.json .
 
+.PHONY: reprepare
+reprepare: clean prepare
+	true
+
 .PHONY: build
 build:
 	cmake --build build -j 6 --target boot.img
@@ -29,6 +33,10 @@ clean:
 	-rm -rf build
 	-rm compile_commands.json
 
+.PHONY: clean-all
+clean-all: clean
+	-rm Makefile
+
 .PHONY: debug
 debug:
 	$(GDB_BIN) --symbols=build/kernel.out --init-eval-command 'set pagination off' --init-eval-command 'target remote:1234' --eval-command 'hbr kernel_main' --eval-command 'c'

+ 9 - 6
include/kernel/interrupt.h

@@ -6,7 +6,8 @@
 extern "C" {
 #endif
 
-#define INTERRUPT_GATE_TYPE (0x8e)
+#define KERNEL_INTERRUPT_GATE_TYPE (0x8e)
+#define USER_INTERRUPT_GATE_TYPE (0xee)
 
 #define PIC_EOI (0x20)
 
@@ -52,18 +53,18 @@ struct page_fault_error_code {
 // stub in assembly MUST be called irqN
 #define SET_UP_IRQ(N, SELECTOR)        \
     ptr_t addr_irq##N = (ptr_t)irq##N; \
-    SET_IDT_ENTRY(0x20 + (N), (addr_irq##N), (SELECTOR));
+    SET_IDT_ENTRY(0x20 + (N), (addr_irq##N), (SELECTOR), KERNEL_INTERRUPT_GATE_TYPE);
 
-#define SET_IDT_ENTRY_FN(N, FUNC_NAME, SELECTOR) \
+#define SET_IDT_ENTRY_FN(N, FUNC_NAME, SELECTOR, TYPE) \
     extern void FUNC_NAME();                     \
     ptr_t addr_##FUNC_NAME = (ptr_t)FUNC_NAME;   \
-    SET_IDT_ENTRY((N), (addr_##FUNC_NAME), (SELECTOR));
+    SET_IDT_ENTRY((N), (addr_##FUNC_NAME), (SELECTOR), (TYPE));
 
-#define SET_IDT_ENTRY(N, ADDR, SELECTOR)      \
+#define SET_IDT_ENTRY(N, ADDR, SELECTOR, TYPE)      \
     IDT[(N)].offset_low = (ADDR)&0x0000ffff;  \
     IDT[(N)].selector = (SELECTOR);           \
     IDT[(N)].zero = 0;                        \
-    IDT[(N)].type_attr = INTERRUPT_GATE_TYPE; \
+    IDT[(N)].type_attr = (TYPE); \
     IDT[(N)].offset_high = ((ADDR)&0xffff0000) >> 16
 
 struct IDT_entry {
@@ -126,6 +127,8 @@ void irq13(void);
 void irq14(void);
 void irq15(void);
 
+void syscall_stub(void);
+
 #ifdef __cplusplus
 }
 #endif

+ 18 - 0
include/kernel/syscall.hpp

@@ -0,0 +1,18 @@
+#pragma once
+
+#include <types/types.h>
+#include <kernel/interrupt.h>
+
+struct PACKED syscall_stack_data {
+    struct regs_32 s_regs;
+    void* v_eip;
+    uint32_t cs;
+    uint32_t eflags;
+    uint32_t esp;
+    uint32_t ss;
+};
+
+// return value is stored in %eax and %edx
+typedef void (*syscall_handler)(syscall_stack_data* data);
+
+void init_syscall(void);

+ 25 - 0
src/asm/interrupt.s

@@ -193,3 +193,28 @@ asm_load_idt:
     sti
 asm_load_idt_skip:
     ret
+
+.globl syscall_stub
+.type  syscall_stub @function
+syscall_stub:
+    cmpl $8, %eax
+    jge syscall_stub_end
+    pushal
+
+    # syscall function no. is in %eax
+    # store it in %ebx
+    movl %eax, %ebx
+    # stack alignment and push *data
+    movl %esp, %eax
+    subl $0x4, %esp
+    andl $0xfffffff0, %esp
+    movl %eax, (%esp)
+
+    call *syscall_handlers(%ebx)
+
+    # restore stack
+    popl %esp
+
+    popal
+syscall_stub_end:
+    iret

+ 13 - 9
src/kernel/interrupt.cpp

@@ -9,6 +9,7 @@
 #include <kernel/mm.hpp>
 #include <kernel/process.hpp>
 #include <kernel/stdio.h>
+#include <kernel/syscall.hpp>
 #include <kernel/tty.h>
 #include <kernel/vga.h>
 #include <kernel_main.h>
@@ -22,13 +23,16 @@ void init_idt()
     memset(IDT, 0x00, sizeof(IDT));
 
     // invalid opcode
-    SET_IDT_ENTRY_FN(6, int6, 0x08);
+    SET_IDT_ENTRY_FN(6, int6, 0x08, KERNEL_INTERRUPT_GATE_TYPE);
     // double fault
-    SET_IDT_ENTRY_FN(8, int8, 0x08);
+    SET_IDT_ENTRY_FN(8, int8, 0x08, KERNEL_INTERRUPT_GATE_TYPE);
     // general protection
-    SET_IDT_ENTRY_FN(13, int13, 0x08);
+    SET_IDT_ENTRY_FN(13, int13, 0x08, KERNEL_INTERRUPT_GATE_TYPE);
     // page fault
-    SET_IDT_ENTRY_FN(14, int14, 0x08);
+    SET_IDT_ENTRY_FN(14, int14, 0x08, KERNEL_INTERRUPT_GATE_TYPE);
+    // system call
+    SET_IDT_ENTRY_FN(0x80, syscall_stub, 0x08, USER_INTERRUPT_GATE_TYPE);
+    init_syscall();
 
     uint16_t idt_descriptor[3];
     idt_descriptor[0] = sizeof(struct IDT_entry) * 256;
@@ -84,7 +88,7 @@ extern "C" void int6_handler(
 {
     char buf[512];
 
-    tty_print(console, "---- INVALID OPCODE ----\n");
+    tty_print(console, "\n---- INVALID OPCODE ----\n");
 
     snprintf(
         buf, 512,
@@ -97,7 +101,7 @@ extern "C" void int6_handler(
         cs, error_code);
     tty_print(console, buf);
 
-    tty_print(console, "----   HALTING SYSTEM   ----");
+    tty_print(console, "----   HALTING SYSTEM   ----\n");
 
     asm_cli();
     asm_hlt();
@@ -113,7 +117,7 @@ extern "C" void int13_handler(
 {
     char buf[512];
 
-    tty_print(console, "---- SEGMENTATION FAULT ----\n");
+    tty_print(console, "\n---- SEGMENTATION FAULT ----\n");
 
     snprintf(
         buf, 512,
@@ -127,7 +131,7 @@ extern "C" void int13_handler(
         cs, error_code, eflags);
     tty_print(console, buf);
 
-    tty_print(console, "----   HALTING SYSTEM   ----");
+    tty_print(console, "----   HALTING SYSTEM   ----\n");
 
     asm_cli();
     asm_hlt();
@@ -207,7 +211,7 @@ extern "C" void int14_handler(struct int14_data* d)
 kill:
     snprintf(
         buf, 512,
-        "killed: segmentation fault (eip: %x, cr2: %x, error_code: %x)", d->v_eip, d->l_addr, d->error_code);
+        "\nkilled: segmentation fault (eip: %x, cr2: %x, error_code: %x)\n", d->v_eip, d->l_addr, d->error_code);
     tty_print(console, buf);
 
     MAKE_BREAK_POINT();

+ 6 - 2
src/kernel/process.cpp

@@ -89,11 +89,15 @@ void NORETURN init_scheduler()
 
     // movl $0x01919810, %eax
     // movl $0x00114514, %ebx
-    // jmp $.
+    // movl $0x00000001, %eax
+    // int $0x80
     unsigned char instruction1[] = {
-        0xb8, 0x10, 0x98, 0x91, 0x01, 0xbb, 0x14, 0x45, 0x11, 0x00, 0xeb, 0xfe
+        0xb8, 0x10, 0x98, 0x91, 0x01, 0xbb, 0x14, 0x45, 0x11, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0xcd, 0x80
     };
 
+    // movl $0x19198100, %eax
+    // movl $0x11451400, %ebx
+    // jmp $.
     uint8_t instruction2[] = {
         0xb8, 0x00, 0x81, 0x19, 0x19, 0xbb, 0x00, 0x14, 0x45, 0x11, 0xeb, 0xfe
     };

+ 27 - 0
src/kernel/syscall.cpp

@@ -0,0 +1,27 @@
+#include <kernel/syscall.hpp>
+
+syscall_handler syscall_handlers[8];
+
+void _syscall_not_impl(syscall_stack_data* data)
+{
+    data->s_regs.eax = 0xffffffff;
+    data->s_regs.edx = 0xffffffff;
+}
+
+void _syscall_fork(syscall_stack_data* data)
+{
+    data->s_regs.eax = 0xfafafafa;
+    data->s_regs.edx = 0xfefefefe;
+}
+
+void init_syscall(void)
+{
+    syscall_handlers[0] = _syscall_fork;
+    syscall_handlers[1] = _syscall_not_impl;
+    syscall_handlers[2] = _syscall_not_impl;
+    syscall_handlers[3] = _syscall_not_impl;
+    syscall_handlers[4] = _syscall_not_impl;
+    syscall_handlers[5] = _syscall_not_impl;
+    syscall_handlers[6] = _syscall_not_impl;
+    syscall_handlers[7] = _syscall_not_impl;
+}