]> git.corax.cc Git - corax/commitdiff
Initial commit, starting with the code base from github master
authorMatthias Kruk <m@m10k.eu>
Tue, 3 Sep 2019 07:05:17 +0000 (16:05 +0900)
committerMatthias Kruk <m@m10k.eu>
Tue, 3 Sep 2019 07:05:17 +0000 (16:05 +0900)
44 files changed:
Makefile [new file with mode: 0644]
config.h [new file with mode: 0644]
include/corax/types.h [new file with mode: 0644]
kernel/Makefile [new file with mode: 0644]
kernel/arch/Makefile [new file with mode: 0644]
kernel/arch/apic.S [new file with mode: 0644]
kernel/arch/apic.h [new file with mode: 0644]
kernel/arch/apic.o [new file with mode: 0644]
kernel/arch/arch.o [new file with mode: 0644]
kernel/arch/boot.S [new file with mode: 0644]
kernel/arch/boot.o [new file with mode: 0644]
kernel/arch/cpu.S [new file with mode: 0644]
kernel/arch/cpu.c [new file with mode: 0644]
kernel/arch/cpu.h [new file with mode: 0644]
kernel/arch/cpu.o [new file with mode: 0644]
kernel/arch/cpu32.S [new file with mode: 0644]
kernel/arch/cpu32.o [new file with mode: 0644]
kernel/arch/debug.c [new file with mode: 0644]
kernel/arch/debug.o [new file with mode: 0644]
kernel/arch/defs.h [new file with mode: 0644]
kernel/arch/entry.S [new file with mode: 0644]
kernel/arch/entry.o [new file with mode: 0644]
kernel/arch/i8259.S [new file with mode: 0644]
kernel/arch/i8259.o [new file with mode: 0644]
kernel/arch/idle.S [new file with mode: 0644]
kernel/arch/init.S [new file with mode: 0644]
kernel/arch/init.o [new file with mode: 0644]
kernel/arch/interrupt.c [new file with mode: 0644]
kernel/arch/interrupt.o [new file with mode: 0644]
kernel/arch/paging.c [new file with mode: 0644]
kernel/arch/paging.h [new file with mode: 0644]
kernel/arch/paging.o [new file with mode: 0644]
kernel/arch/task.S [new file with mode: 0644]
kernel/arch/task.h [new file with mode: 0644]
kernel/arch/task.o [new file with mode: 0644]
kernel/core/Makefile [new file with mode: 0644]
kernel/core/core.o [new file with mode: 0644]
kernel/core/main.c [new file with mode: 0644]
kernel/core/main.o [new file with mode: 0644]
kernel/include/arch.h [new file with mode: 0644]
kernel/include/assembly.h [new file with mode: 0644]
kernel/include/debug.h [new file with mode: 0644]
kernel/include/multiboot.h [new file with mode: 0644]
kernel/linker.ld [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..7782996
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,23 @@
+DEPS = kernel
+OUTPUT = corax
+PHONY = $(DEPS) clean qemu
+LAYOUT = $(shell setxkbmap -query | sed -nE 's/^layout:.*?([a-z]{2})$/\1/p')
+
+foo:
+       $(eval setxkbmap -query | sed -nE 's/^layout:.*?([a-z]{2})$/\1/p')
+
+all: $(OUTPUT)
+
+qemu:
+       qemu-system-x86_64 -k ja -kernel $(OUTPUT) -m 512
+
+$(OUTPUT): $(DEPS)
+       mv kernel/corax $(OUTPUT)
+
+$(DEPS):
+       $(MAKE) -C $@ $(MAKECMDGOALS)
+
+clean: $(DEPS)
+       rm -f $(OUTPUT)
+
+.PHONY: $(PHONY)
diff --git a/config.h b/config.h
new file mode 100644 (file)
index 0000000..d0d930f
--- /dev/null
+++ b/config.h
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the Corax operating system.
+ * Copyright (C) 2016 Matthias Kruk
+ *
+ * Corax is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Corax is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Corax.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#define CONFIG_KERNEL_STACK_SIZE    4096
+#define CONFIG_USER_STACK_SIZE      4096
+
+#define CONFIG_APIC     1
+
+#define CONFIG_SMP      0
+#define CONFIG_SMP_CPUS 1
+
+/* sanity checks */
+
+#if !defined(CONFIG_SMP_CPUS) || CONFIG_SMP_CPUS == 0
+#error "CONFIG_SMP_CPUS can't be undefined or zero"
+#endif /* !defined(CONFIG_SMP_CPUS) */
+
+#if CONFIG_SMP == 0 && CONFIG_SMP_CPUS > 1
+#error "CONFIG_SMP_CPUS must be 1 if compiling without SMP support"
+#endif /* CONFIG_SMP == 0 && CONFIG_SMP_CPUS > 1 */
+
+#endif /* __CONFIG_H */
diff --git a/include/corax/types.h b/include/corax/types.h
new file mode 100644 (file)
index 0000000..7e5f445
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * This file is part of the Corax operating system.
+ * Copyright (C) 2016 Matthias Kruk
+ *
+ * Corax is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Corax is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Corax.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TYPES_H
+#define __TYPES_H
+
+typedef unsigned char           u8_t;
+typedef unsigned short          u16_t;
+typedef unsigned int            u32_t;
+typedef unsigned long long int  u64_t;
+
+typedef signed char             i8_t;
+typedef signed short            i16_t;
+typedef signed int              i32_t;
+typedef signed long long int    i64_t;
+
+#define NULL    ((void*)0)
+#define FALSE   0
+#define TRUE    (!FALSE)
+
+#endif /* __TYPES_H */
diff --git a/kernel/Makefile b/kernel/Makefile
new file mode 100644 (file)
index 0000000..a5c7548
--- /dev/null
@@ -0,0 +1,22 @@
+OBJECTS = arch/arch.o core/core.o
+DEPS = arch core
+LDFLAGS = --oformat=elf32-i386 -b elf32-i386 -m elf_i386
+CFLAGS = -m32 -Wall -nostdlib -nodefaultlibs -nostartfiles -ffreestanding
+PHONY = $(DEPS) clean
+OUTPUT = corax
+
+export LDFLAGS
+export CFLAGS
+
+all: $(OUTPUT)
+
+$(DEPS):
+       $(MAKE) -C $@ $(MAKECMDGOALS)
+
+$(OUTPUT): $(DEPS)
+       ld -o $@ -T linker.ld $(LDFLAGS) $(OBJECTS)
+
+clean: $(DEPS)
+       rm -f $(OUTPUT)
+
+.PHONY: $(PHONY)
diff --git a/kernel/arch/Makefile b/kernel/arch/Makefile
new file mode 100644 (file)
index 0000000..67a8275
--- /dev/null
@@ -0,0 +1,23 @@
+OBJECTS = boot.o debug.o init.o cpu.o cpu32.o entry.o interrupt.o paging.o apic.o i8259.o task.o
+OUTPUT = arch.o
+LDFLAGS += -r
+INCLUDES = -I../../include -I../include -I../..
+CFLAGS += $(INCLUDES)
+PHONY = clean
+
+ifeq (0,$(MAKELEVEL))
+LDFLAGS = --oformat=elf32-i386 -b elf32-i386 -m elf_i386 -r
+CFLAGS = -m32 -Wall -nostdlib -nodefaultlibs -nostartfiles -ffreestanding $(INCLUDES)
+endif
+ASFLAGS = $(CFLAGS)
+
+all: $(OUTPUT)
+
+$(OUTPUT): $(OBJECTS)
+       ld $(LDFLAGS) -o $@ $^
+
+clean:
+       rm -f $(OBJECTS) $(OUTPUT)
+
+
+.PHONY: $(PHONY)
diff --git a/kernel/arch/apic.S b/kernel/arch/apic.S
new file mode 100644 (file)
index 0000000..986199b
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * This file is part of the Corax operating system.
+ * Copyright (C) 2016 Matthias Kruk
+ *
+ * Corax is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Corax is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Corax.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include "defs.h"
+#include "apic.h"
+
+.extern dbg_printf
+.extern _segment_descriptor_set
+.extern _cpu
+.extern _int_entry_common
+
+.section .text
+
+.global _apic_init
+.global _apic_eoi
+
+_int_entry_apicerr:
+    subl    $8, %eax
+    movl    %eax, (%esp)
+    movl    APIC_ESR, %eax
+    movl    %eax, 4(%esp)
+    movl    (%esp), %eax
+    movl    $INT(-2), (%esp)
+    jmp     _int_entry_common
+
+_int_entry_spurious:
+    pushl   $0
+    pushl   $INT(-1)
+    jmp     _int_entry_common
+
+_apic_eoi:
+    xorl    %eax, %eax
+    movl    %eax, APIC_EOIR
+    ret
+
+_apic_init:
+    subl    $20, %esp
+    movl    $_fmt_apic, (%esp)
+    call    dbg_printf
+
+    movl    APIC_VERSION, %eax
+    movl    %eax, 4(%esp)
+    movl    $_fmt_apic_ver, (%esp)
+    call    dbg_printf
+
+    /* add handlers for APIC error and spurious interrupts to IDT */
+    movl    $_cpu, %eax
+    addl    $IDT_OFFSET, %eax
+    addl    $(INT(-2) * 8), %eax
+
+    movl    $DPL_USER, 16(%esp)
+    movl    $_int_entry_apicerr, 12(%esp)
+    movl    $0x8, 8(%esp)
+    movl    $SD_TYPE_INT_GATE, 4(%esp)
+    movl    %eax, (%esp)
+    call    _segment_descriptor_set
+
+    movl    $_int_entry_spurious, 12(%esp)
+    addl    $8, (%esp)
+    call    _segment_descriptor_set
+
+    /* set the divisor and initial count of the timer */
+    movl    $0xb, APIC_TIMER_DIVISOR
+    movl    $1000, APIC_TIMER_INITCNT
+
+    /* set up LVT entries for timer, error, spurious interrupts */
+
+    movl    $INT(0), %eax
+    orl     $APIC_TIMER_PERIODIC, %eax
+    movl    %eax, APIC_LVT_TIMER
+
+    movl    $INT(-2), APIC_LVT_ERROR
+
+    movl    APIC_SVR, %eax
+    andl    $0xfffffe00, %eax
+    movb    $INT(-1), %al
+    orl     $APIC_SVR_ENABLE, %eax  /* and software-enable the APIC */
+    movl    %eax, APIC_SVR
+
+/*
+    movl    APIC_ESR, %eax
+    movl    %eax, 8(%esp)
+    movl    APIC_SVR, %eax
+    movl    %eax, 4(%esp)
+    movl    $_fmt_apic_regs, (%esp)
+    call    dbg_printf
+*/
+
+    /* next, set up the IO-APIC redirection table */
+    xorl    %eax, %eax
+    xorl    %ebx, %ebx
+/*
+    movb    $0x12, IOAPIC_INDEX
+    movl    IOAPIC_DATA, %eax
+    movl    %eax, %edx
+
+    andl    $0xfffeff80, %eax
+    movb    $(INT_VECTOR0 + 1), %al
+
+    movb    $0x12, IOAPIC_INDEX
+    movl    %eax, IOAPIC_DATA
+
+    movl    %eax, 12(%esp)
+    movl    %edx, 8(%esp)
+    movl    $1, 4(%esp)
+    movl    $_fmt_ioapic_rt, (%esp)
+    call    dbg_printf
+*/
+    xorl    %ecx, %ecx
+    0:
+    cmpl    $IOAPIC_LINES, %ecx
+    jge     1f
+
+    /* calculate redirection table index */
+    movb    %cl, %bl
+    shlb    $1, %bl
+    addb    $IOAPIC_IDX_RTL, %bl
+
+    /* load, modify entry, write back */
+    movb    %bl, IOAPIC_INDEX
+    movl    IOAPIC_DATA, %eax
+/* *** This is only necessary along with the next comment block ***
+    movl    %eax, %edx
+*/
+    andl    $0xfffef800, %eax /* set mask, delivery mode, vector to zero */
+    movb    $INT_VECTOR0, %al
+    addb    %cl, %al
+
+       /* mask INT(2) [cascaded i8259] on APIC systems */
+       cmp             $INT(2), %al
+       jnz             2f
+       orl             $0x00010000, %eax
+2:     
+/* *** Previous comment block is required for this to work properly ***
+    movl    %eax, 16(%esp)
+    movl    %edx, 12(%esp)
+    movl    %ebx, 8(%esp)
+    movl    %ecx, 4(%esp)
+    movl    $_fmt_ioapic_rt, (%esp)
+    call    dbg_printf
+
+    movl    4(%esp), %ecx
+    movl    8(%esp), %ebx
+    movl    16(%esp), %eax
+*/
+    movb    %bl, IOAPIC_INDEX
+    movl    %eax, IOAPIC_DATA
+
+    inc     %ecx
+    jmp     0b
+    1:
+
+    /* adjust the IMCR so interrupts will be sent to the IO-APIC */
+
+    movb    $IMCR_ADDR, %al
+    outb    %al, $IMCR_COMM
+    movb    $IMCR_APIC, %al
+    outb    %al, $IMCR_DATA
+
+    addl    $20, %esp
+    ret
+
+.section .data
+
+_fmt_apic:
+    .asciz  "Initialising APIC\n"
+_fmt_apic_ver:
+    .asciz  "APIC_VER = 0x%08x\n"
+_fmt_apic_regs:
+    .asciz  "SVR: 0x%08x; ESR: 0x%08x\n"
+_fmt_ioapic_rt:
+    .asciz  "RT[%u,0x%x]L: 0x%08x -> 0x%08x\n"
diff --git a/kernel/arch/apic.h b/kernel/arch/apic.h
new file mode 100644 (file)
index 0000000..98a4e38
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * This file is part of the Corax operating system.
+ * Copyright (C) 2016 Matthias Kruk
+ *
+ * Corax is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Corax is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Corax.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __APIC_H
+#define __APIC_H
+
+#define APIC_BASE           0xfee00000
+
+#define APIC_ID             (APIC_BASE + 0x20)
+#define APIC_VERSION        (APIC_BASE + 0x30)
+#define APIC_TPR            (APIC_BASE + 0x80)
+#define APIC_APR            (APIC_BASE + 0x90)
+#define APIC_PPR            (APIC_BASE + 0xa0)
+#define APIC_EOIR           (APIC_BASE + 0xb0)
+#define APIC_RRD            (APIC_BASE + 0xc0)
+#define APIC_LDR            (APIC_BASE + 0xd0)
+#define APIC_DFR            (APIC_BASE + 0xe0)
+#define APIC_SVR            (APIC_BASE + 0xf0)
+
+#define APIC_ISR0           (APIC_BASE + 0x100)
+#define APIC_ISR1           (APIC_BASE + 0x110)
+#define APIC_ISR2           (APIC_BASE + 0x120)
+#define APIC_ISR3           (APIC_BASE + 0x130)
+#define APIC_ISR4           (APIC_BASE + 0x140)
+#define APIC_ISR5           (APIC_BASE + 0x150)
+#define APIC_ISR6           (APIC_BASE + 0x160)
+#define APIC_ISR7           (APIC_BASE + 0x170)
+
+#define APIC_TMR0           (APIC_BASE + 0x180)
+#define APIC_TMR1           (APIC_BASE + 0x190)
+#define APIC_TMR2           (APIC_BASE + 0x1a0)
+#define APIC_TMR3           (APIC_BASE + 0x1b0)
+#define APIC_TMR4           (APIC_BASE + 0x1c0)
+#define APIC_TMR5           (APIC_BASE + 0x1d0)
+#define APIC_TMR6           (APIC_BASE + 0x1e0)
+#define APIC_TMR7           (APIC_BASE + 0x1f0)
+
+#define APIC_IRR0           (APIC_BASE + 0x200)
+#define APIC_IRR1           (APIC_BASE + 0x210)
+#define APIC_IRR2           (APIC_BASE + 0x220)
+#define APIC_IRR3           (APIC_BASE + 0x230)
+#define APIC_IRR4           (APIC_BASE + 0x240)
+#define APIC_IRR5           (APIC_BASE + 0x250)
+#define APIC_IRR6           (APIC_BASE + 0x260)
+#define APIC_IRR7           (APIC_BASE + 0x270)
+
+#define APIC_ESR            (APIC_BASE + 0x280)
+
+#define APIC_ICR_LOW        (APIC_BASE + 0x300)
+#define APIC_ICR_HIGH       (APIC_BASE + 0x310)
+
+#define APIC_LVT_CMCI       (APIC_BASE + 0x2f0)
+#define APIC_LVT_TIMER      (APIC_BASE + 0x320)
+#define APIC_LVT_THERMAL    (APIC_BASE + 0x330)
+#define APIC_LVT_PERF       (APIC_BASE + 0x340)
+#define APIC_LVT_LINT0      (APIC_BASE + 0x350)
+#define APIC_LVT_LINT1      (APIC_BASE + 0x360)
+#define APIC_LVT_ERROR      (APIC_BASE + 0x370)
+
+#define APIC_TIMER_INITCNT  (APIC_BASE + 0x380)
+#define APIC_TIMER_CURCNT   (APIC_BASE + 0x390)
+#define APIC_TIMER_DIVISOR  (APIC_BASE + 0x3e0)
+
+#define APIC_TIMER_ONESHOT  0
+#define APIC_TIMER_PERIODIC 0x20000
+#define APIC_SVR_ENABLE     0x100
+
+/* definitions for the IO-APIC */
+
+#define IOAPIC_LINES        24
+
+#define IOAPIC_BASE         0xfec00000
+
+#define IOAPIC_INDEX        (IOAPIC_BASE + 0x00)
+#define IOAPIC_DATA         (IOAPIC_BASE + 0x10)
+#define IOAPIC_IRQ_PAR      (IOAPIC_BASE + 0x20)
+#define IOAPIC_EOIR         (IOAPIC_BASE + 0x40)
+
+#define IOAPIC_IDX_IDR      0
+#define IOAPIC_IDX_VERSION  1
+#define IOAPIC_IDX_RTL      0x10
+#define IOAPIC_IDX_RTH      0x11
+
+#define IMCR_COMM           0x22
+#define IMCR_DATA           0x23
+#define IMCR_ADDR           0x70
+
+#define IMCR_APIC           1
+#define IMCR_I8259          0
+
+#endif /* __APIC_H */
diff --git a/kernel/arch/apic.o b/kernel/arch/apic.o
new file mode 100644 (file)
index 0000000..78dd5e0
Binary files /dev/null and b/kernel/arch/apic.o differ
diff --git a/kernel/arch/arch.o b/kernel/arch/arch.o
new file mode 100644 (file)
index 0000000..b02a94b
Binary files /dev/null and b/kernel/arch/arch.o differ
diff --git a/kernel/arch/boot.S b/kernel/arch/boot.S
new file mode 100644 (file)
index 0000000..7e53bf1
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the Corax operating system.
+ * Copyright (C) 2016 Matthias Kruk
+ *
+ * Corax is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Corax is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Corax.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "defs.h"
+
+.global loader
+.extern corax
+.extern _cpu
+
+#define FLAGS 2
+#define MAGIC 0x1BADB002
+#define CKSUM -(MAGIC + FLAGS)
+
+.section .text
+.align 4
+
+_mb_header:
+    .long   MAGIC
+    .long   FLAGS
+    .long   CKSUM
+
+loader:
+    cli
+    movl    $_cpu, %esp
+    addl    $STACK0_TOP, %esp
+    pushl   %eax
+    pushl   %ebx
+    call    corax
+    addl    $8, %esp
+    cli
+    hlt
diff --git a/kernel/arch/boot.o b/kernel/arch/boot.o
new file mode 100644 (file)
index 0000000..18094cc
Binary files /dev/null and b/kernel/arch/boot.o differ
diff --git a/kernel/arch/cpu.S b/kernel/arch/cpu.S
new file mode 100644 (file)
index 0000000..9b48793
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * This file is part of the Corax operating system.
+ * Copyright (C) 2016 Matthias Kruk
+ *
+ * Corax is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Corax is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Corax.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+.section .text
+
+.equ    LCR_LOW, 0xfee00300
+.equ    SVR, 0xfee000f0
+.equ    APIC_ID, 0xfee00020
+.equ    LVT3, 0xfee00370
+.equ    APIC_ENABLED, 0x100
+boot_id:
+.long   0
+.equ    COUNT, 0
+.equ    VACANT, 0
+
+.global cpu_get_id
+
+cpu_get_id:
+    movl    APIC_ID, %eax
+    shrl    $24, %eax
+    ret
diff --git a/kernel/arch/cpu.c b/kernel/arch/cpu.c
new file mode 100644 (file)
index 0000000..7164830
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * This file is part of the Corax operating system.
+ * Copyright (C) 2016 Matthias Kruk
+ *
+ * Corax is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Corax is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Corax.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <corax/types.h>
+#include <debug.h>
+#include "defs.h"
+#include "cpu.h"
+
+struct cpu _cpu[CONFIG_SMP_CPUS];
+
+#if defined(CONFIG_SMP) && CONFIG_SMP_CPUS > 1
+
+int cpu_get_id(void) {
+    /* FIXME: implement this properly */
+    return(0);
+}
+
+#endif /* CONFIG_SMP */
+
+void _segment_descriptor_set(segment_descriptor_t *sd, u32_t type, u32_t base, u32_t limit, u32_t dpl) {
+        sd->sd_high = type;
+        switch(type) {
+                case SD_TYPE_CODE:
+                case SD_TYPE_DATA:
+                case SD_TYPE_TSS:
+                        sd->sd_low = (limit & 0xffff) | ((base << 16) & 0xffff0000);
+                        sd->sd_high |= (base & 0xff000000) | ((base >> 16) & 0xff);
+                        sd->sd_high |= (limit & 0xf0000) | dpl;
+                        break;
+                case SD_TYPE_TASK_GATE:
+                        sd->sd_low = (base << 16) & 0xffff0000;
+                        sd->sd_high |= dpl;
+                        break;
+                case SD_TYPE_INT_GATE:
+                case SD_TYPE_CALL_GATE:
+                case SD_TYPE_TRAP_GATE:
+                        sd->sd_low = ((base << 16) & 0xffff0000) | (limit & 0xffff);
+                        sd->sd_high |= (limit & 0xffff0000) | dpl;
+                        break;
+                default:
+                        PANIC("Invalid segment descriptor type");
+                        break;
+        }
+        return;
+}
+
+void cpu_debug(void) {
+    u32_t i;
+
+    for(i = 0; i < 256; i++) {
+        segment_descriptor_t *sd = &(_cpu[0].cpu_idt[i]);
+        u32_t addr;
+
+        if(!sd->sd_high && !sd->sd_low && i) {
+            continue;
+        }
+
+        if((sd->sd_high & 0xf00) == 0xe00) {
+            addr = (sd->sd_high & 0xffff0000) | (sd->sd_low & 0x0000ffff);
+            dbg_printf("[%u]=0x%x ", i, addr);
+        } else {
+            dbg_printf("[%u]G!=0x%08x:%08x ", i, sd->sd_high, sd->sd_low);
+        }
+    }
+
+    return;
+}
diff --git a/kernel/arch/cpu.h b/kernel/arch/cpu.h
new file mode 100644 (file)
index 0000000..0cd8c66
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * This file is part of the Corax operating system.
+ * Copyright (C) 2016 Matthias Kruk
+ *
+ * Corax is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Corax is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Corax.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __CPU_H
+#define __CPU_H
+
+#include <corax/types.h>
+#include "defs.h"
+
+typedef struct segment_descriptor segment_descriptor_t;
+typedef u16_t segment_selector_t;
+
+struct segment_descriptor {
+    u32_t sd_low;
+    u32_t sd_high;
+} __attribute__((packed));
+
+typedef struct tss32 tss32_t;
+
+struct tss32 {
+    u16_t   tss_tr;
+    u16_t   tss_resv0;
+
+    u32_t   tss_esp0;
+    u16_t   tss_ss0;
+    u16_t   tss_resv1;
+
+    u32_t   tss_esp1;
+    u16_t   tss_ss1;
+    u16_t   tss_resv2;
+
+    u32_t   tss_esp2;
+    u16_t   tss_ss2;
+    u16_t   tss_resv3;
+
+    u32_t   tss_cr3;
+    u32_t   tss_eip;
+    u32_t   tss_eflags;
+
+    u32_t   tss_eax;
+    u32_t   tss_ecx;
+    u32_t   tss_edx;
+    u32_t   tss_ebx;
+    u32_t   tss_esp;
+    u32_t   tss_ebp;
+    u32_t   tss_esi;
+    u32_t   tss_edi;
+
+    u16_t   tss_es;
+    u16_t   tss_resv4;
+    u16_t   tss_cs;
+    u16_t   tss_resv5;
+    u16_t   tss_ss;
+    u16_t   tss_resv6;
+    u16_t   tss_ds;
+    u16_t   tss_resv7;
+    u16_t   tss_fs;
+    u16_t   tss_resv8;
+    u16_t   tss_gs;
+    u16_t   tss_resv9;
+    u16_t   tss_ldtr;
+    u16_t   tss_trap;
+    u16_t   tss_iomap;
+} __attribute__((packed));
+
+typedef struct tss64 tss64_t;
+
+struct tss64 {
+    u32_t   tss64_resv0;
+    u32_t   tss64_rsp0l;
+    u32_t   tss64_rsp0h;
+    u32_t   tss64_rsp1l;
+    u32_t   tss64_rsp1h;
+    u32_t   tss64_rsp2l;
+    u32_t   tss64_rsp2h;
+    u32_t   tss64_resv1;
+    u32_t   tss64_resv2;
+    u32_t   tss64_ist1l;
+    u32_t   tss64_ist1h;
+    u32_t   tss64_ist2l;
+    u32_t   tss64_ist2h;
+    u32_t   tss64_ist3l;
+    u32_t   tss64_ist3h;
+    u32_t   tss64_ist4l;
+    u32_t   tss64_ist4h;
+    u32_t   tss64_ist5l;
+    u32_t   tss64_ist5h;
+    u32_t   tss64_ist6l;
+    u32_t   tss64_ist6h;
+    u32_t   tss64_ist7l;
+    u32_t   tss64_ist7h;
+    u32_t   rss64_resv3;
+    u32_t   rss64_resv4;
+    u16_t   rss64_resv5;
+    u16_t   rss64_iomap;
+} __attribute__((packed));
+
+typedef struct stack_frame stack_frame_t;
+
+struct stack_frame {
+        u32_t ds;       /* + 0x00 / 00 */
+        u32_t edi;      /* + 0x04 / 04 */
+        u32_t esi;      /* + 0x08 / 08 */
+        u32_t ebp;      /* + 0x0c / 12 */
+        u32_t esp;      /* + 0x10 / 16 */
+        u32_t ebx;      /* + 0x14 / 20 */
+        u32_t edx;      /* + 0x18 / 24 */
+        u32_t ecx;      /* + 0x1c / 28 */
+        u32_t eax;      /* + 0x20 / 32 */
+        u32_t intn;     /* + 0x24 / 36 */
+        u32_t error;
+        u32_t eip;
+        u32_t cs;
+        u32_t eflags;
+        u32_t prevesp;
+        u32_t ss;
+} __attribute__((packed));
+
+struct cpu {
+    u8_t                    cpu_stack0[STACK0_SIZE];
+    segment_descriptor_t    cpu_gdt[GDT_ENTRIES];
+    segment_descriptor_t    cpu_idt[IDT_ENTRIES];
+    tss32_t                 cpu_tss;
+    struct task             *cpu_task;
+} __attribute__((packed));
+
+#if defined(CONFIG_SMP) && CONFIG_SMP_CPUS > 1
+
+int cpu_get_id(void);
+#define CPU_ID  cpu_get_id()
+
+#else
+
+#define CPU_ID  0
+
+#endif /* CONFIG_SMP */
+
+
+void _segment_descriptor_set(segment_descriptor_t*, u32_t, u32_t, u32_t, u32_t);
+
+#endif /* __CPU_H */
diff --git a/kernel/arch/cpu.o b/kernel/arch/cpu.o
new file mode 100644 (file)
index 0000000..b4a094a
Binary files /dev/null and b/kernel/arch/cpu.o differ
diff --git a/kernel/arch/cpu32.S b/kernel/arch/cpu32.S
new file mode 100644 (file)
index 0000000..211f3d1
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * This file is part of the Corax operating system.
+ * Copyright (C) 2016 Matthias Kruk
+ *
+ * Corax is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Corax is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Corax.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "defs.h"
+
+.section .text
+
+/*
+.equ    LCR_LOW, 0xfee00300
+.equ    SVR, 0xfee000f0
+.equ    APIC_ID, 0xfee00020
+.equ    LVT3, 0xfee00370
+.equ    APIC_ENABLED, 0x100
+boot_id:
+.long   0
+.equ    COUNT, 0
+.equ    VACANT, 0
+*/
+
+.global cpu_get_id
+
+cpu_get_id:
+    movl    $APIC_ID_ADDR, %esi
+    movl    (%esi), %eax
+    shrl    $24, %eax
+    ret
+
+.global cpu_get_capabilities
+
+cpu_get_capabilities:
+    movl    $1, %eax
+    cpuid
+    movl    %ecx, %eax
+    ret
+
+.global cpu_timestamp
+cpu_timestamp:
+    lfence
+    rdtsc
+    ret
+
+.global cpu_set_pstate
+
+cpu_set_pstate:
+       pushl   %ebx
+       movl    $0x199, %ecx
+       rdmsr
+       movl    8(%esp), %ebx
+       movw    %bx, %ax
+       wrmsr
+       popl    %ebx
+       ret
diff --git a/kernel/arch/cpu32.o b/kernel/arch/cpu32.o
new file mode 100644 (file)
index 0000000..3562e2d
Binary files /dev/null and b/kernel/arch/cpu32.o differ
diff --git a/kernel/arch/debug.c b/kernel/arch/debug.c
new file mode 100644 (file)
index 0000000..0467265
--- /dev/null
@@ -0,0 +1,474 @@
+/*
+ * This file is part of the Corax operating system.
+ * Copyright (C) 2016 Matthias Kruk
+ *
+ * Corax is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Corax is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Corax.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <corax/types.h>
+#include <debug.h>
+
+#define ABS(x)  (((x) < 0) ? (-(x)) : (x))
+
+#define VGA_BLACK           0
+#define VGA_BLUE            1
+#define VGA_GREEN           2
+#define VGA_CYAN            3
+#define VGA_RED             4
+#define VGA_MAGENTA         5
+#define VGA_BROWN           6
+#define VGA_LIGHT_GRAY      7
+#define VGA_GRAY            8
+#define VGA_LIGHT_BLUE      9
+#define VGA_LIGHT_GREEN     0xa
+#define VGA_LIGHT_CYAN      0xb
+#define VGA_LIGHT_RED       0xc
+#define VGA_LIGHT_MAGENTA   0xd
+#define VGA_YELLOW          0xe
+#define VGA_WHITE           0xf
+
+#define VGA_FONT(c)         ((u16_t)(((c) & 0xf) << 8))
+#define VGA_BACKGROUND(c)   ((u16_t)(((c) & 0xf) << 12))
+
+#define VGA_BUFFER_ADDR    ((void*)0xb8000)
+#define VGA_BUFFER_COLS    80
+#define VGA_BUFFER_ROWS    24
+#define VGA_ROW_BYTES      (VGA_BUFFER_COLS << 1)
+#define VGA_SCROLL_SIZE    (VGA_BUFFER_COLS * (VGA_BUFFER_ROWS - 1))
+#define VGA_SCROLL_BYTES   (VGA_BUFFER_SIZE << 1)
+#define VGA_BUFFER_SIZE    (VGA_BUFFER_COLS * VGA_BUFFER_ROWS)
+#define VGA_BUFFER_BYTES   (VGA_BUFFER_SIZE << 1)
+
+static const char alpha_lc[] = "0123456789abcdef";
+static const char alpha_uc[] = "0123456789ABCDEF";
+static const char nullstr[] = "(null)";
+
+static u16_t* const vga_buffer = VGA_BUFFER_ADDR;
+static u16_t vga_attrs = VGA_FONT(VGA_LIGHT_GRAY) | VGA_BACKGROUND(VGA_BLACK);
+static i32_t vga_offset = VGA_BUFFER_SIZE;
+
+#define VGA_SET_FONT(c)         vga_attrs = (vga_attrs & 0xf0ff) | VGA_FONT(c)
+#define VGA_SET_BACKGROUND(c)   vga_attrs = (vga_attrs & 0x0fff) | VGA_BACKGROUND(c)
+
+i64_t _i64div(i64_t dividend, i64_t divisor) {
+    i64_t quotient;
+    int sign;
+
+    if(divisor == 0) {
+        PANIC("Can't divide by zero");
+    }
+
+    quotient = 0;
+    sign = 1;
+
+    if(dividend < 0) {
+        sign = -sign;
+        dividend = -dividend;
+    }
+
+    if(divisor < 0) {
+        sign = -sign;
+        divisor = -divisor;
+    }
+
+    while(dividend >= divisor) {
+        dividend -= divisor;
+        quotient++;
+    }
+
+    return(sign > 0 ? quotient : -quotient);
+}
+
+i64_t _i64mod(i64_t dividend, i64_t divisor) {
+    if(divisor == 0) {
+        PANIC("Can't divide by zero");
+    }
+
+    if(dividend < 0) {
+        dividend = -dividend;
+    }
+
+    if(divisor < 0) {
+        divisor = -divisor;
+    }
+
+    while(dividend >= divisor) {
+        dividend -= divisor;
+    }
+
+    return(dividend);
+}
+
+u64_t _u64div(u64_t dividend, u64_t divisor) {
+    u64_t quotient = 0;
+
+    if(divisor == 0) {
+        PANIC("Can't divide by zero");
+    }
+
+    while(dividend >= divisor) {
+        dividend -= divisor;
+        quotient++;
+    }
+    return(quotient);
+}
+
+u64_t _u64mod(u64_t dividend, u64_t divisor) {
+    if(divisor == 0) {
+        PANIC("Can't divide by zero");
+    }
+
+    while(dividend >= divisor) {
+        dividend -= divisor;
+    }
+
+    return(dividend);
+}
+
+void* memset(void *dst, int val, u32_t n) {
+    char *ptr;
+
+    ptr = dst;
+    while(n--) {
+        *ptr++ = val;
+    }
+    return(dst);
+}
+
+void* memcpy(void *dst, const void *src, u32_t n) {
+    char *d;
+    const char *s;
+
+    d = dst;
+    s = src;
+    while(n--) {
+        *d++ = *s++;
+    }
+    return(dst);
+}
+
+static void _putchar(int c) {
+    if(c == '\n') {
+        vga_offset += VGA_BUFFER_COLS - (vga_offset % VGA_BUFFER_COLS);
+    } else {
+        if(vga_offset >= VGA_BUFFER_SIZE) {
+            vga_offset = VGA_SCROLL_SIZE;
+            memcpy((void*)vga_buffer, (void*)vga_buffer + VGA_ROW_BYTES, VGA_SCROLL_BYTES);
+            memset((void*)vga_buffer + VGA_SCROLL_BYTES, 0, VGA_ROW_BYTES);
+        }
+
+        vga_buffer[vga_offset++] = vga_attrs | (c & 0xff);
+    }
+
+    return;
+}
+
+int dbg_printf(const char *format, ...) {
+    int n;
+    char c;
+    char size;
+    u32_t *arg;
+    int mode;
+    u32_t flags;
+    int pad;
+    const char *fmt;
+
+    #define MODE_NORMAL 0
+    #define MODE_CONV   1
+    #define FLAG_SIGN   (1 << 31)
+    #define FLAG_PAD    (1 << 30)
+    #define FLAG_LCHEX  (1 << 29)
+
+    n = 0;
+    fmt = format;
+    arg = ((u32_t*)&format) + 1;
+    mode = 0;
+    flags = 0;
+    size = 0;
+    pad = 0;
+
+    while((c = *fmt++)) {
+        if(c == '%') {
+            if(mode == MODE_CONV) {
+                _putchar('%');
+                n++;
+                mode = MODE_NORMAL;
+            } else {
+                mode = MODE_CONV;
+                flags = 0;
+                size = 0;
+                pad = 0;
+            }
+            continue;
+        }
+
+        if(mode == MODE_CONV) {
+            switch(c) {
+                case '+':
+                    flags |= FLAG_SIGN;
+                    break;
+                case '*':
+                    /* TODO: Implement formats like %*s */
+                    flags = (flags & 0xffff0000) | ((int)*arg++ & 0xffff);
+                    break;
+                case 'h':
+                    if(size == 0) {
+                        size = 2;
+                    } else if(size == 2) {
+                        size = 1;
+                    }
+                    break;
+                case 'l':
+                    if(size == 0) {
+                        size = 4;
+                    } else if(size == 4) {
+                        case 'L': /* for double-precision floats, i.e. %Lf */
+                        size = 8;
+                    }
+                    break;
+                case '0':
+                    if(flags & FLAG_PAD) {
+                        pad *= 10;
+                    } else {
+                        flags |= FLAG_PAD;
+                    }
+                    break;
+                case '1':
+                case '2':
+                case '3':
+                case '4':
+                case '5':
+                case '6':
+                case '7':
+                case '8':
+                case '9':
+                    pad *= 10;
+                    pad += (c - '0');
+                    break;
+                case 'd':
+                case 'i': {
+                    i64_t i_arg;
+                    char sstr[20];
+                    int i;
+                    char sign;
+
+                    switch(size) {
+                        case 1:
+                            i_arg = (i8_t)(*arg++ & 0xff);
+                            break;
+                        case 2:
+                            i_arg = (i16_t)(*arg++ & 0xffff);
+                            break;
+                        case 0:
+                        case 4:
+                            i_arg = (i32_t)(*arg++ & 0xffffffff);
+                            break;
+                        case 8:
+                            i_arg = *((i64_t*)arg);
+                            arg += 2;
+                            break;
+                        default:
+                            PANIC("Invalid argument width in format string\n");
+                    }
+
+                    sign = (i_arg < 0) ? '-' : ((flags & FLAG_SIGN) ? '+' : 0);
+                    i = 0;
+
+                    do {
+                        i64_t m;
+
+                        m = _i64mod(i_arg, 10);
+                        sstr[i++] = '0' + ABS(m);
+                        i_arg = _i64div(i_arg, 10);
+                    } while(i_arg != 10);
+
+                    if(sign) {
+                        _putchar(sign);
+                        n++;
+                    }
+
+                    if(flags & FLAG_PAD) {
+                        pad -= i;
+
+                        while(pad-- > 0) {
+                            _putchar('0');
+                            n++;
+                        }
+                    }
+
+                    for(i--; i >= 0; i--) {
+                        _putchar(sstr[i]);
+                        n++;
+                    }
+                    mode = MODE_NORMAL;
+                    break;
+                }
+                case 'u': {
+                    u64_t u_arg;
+                    char sstr[20];
+                    int i;
+
+                    i = 0;
+
+                    switch(size) {
+                        case 1:
+                            u_arg = (u8_t)(*arg++ & 0xff);
+                            break;
+                        case 2:
+                            u_arg = (u16_t)(*arg++ & 0xffff);
+                            break;
+                        case 0:
+                        case 4:
+                            u_arg = (u32_t)(*arg++ & 0xffffffff);
+                            break;
+                        case 8:
+                            u_arg = *((u64_t*)arg);
+                            arg += 2;
+                            break;
+                        default:
+                            PANIC("Invalid argument width in format string\n");
+                    }
+
+                    do {
+                        sstr[i++] = '0' + _u64mod(u_arg, 10);
+                        u_arg = _u64div(u_arg, 10);
+                    } while(u_arg > 0);
+
+                    if(flags & FLAG_SIGN) {
+                        _putchar('+');
+                        n++;
+                    }
+
+                    if(flags & FLAG_PAD) {
+                        pad -= i;
+
+                        while(pad-- > 0) {
+                            _putchar('0');
+                            n++;
+                        }
+                    }
+
+                    for(i--; i >= 0; i--) {
+                        _putchar(sstr[i]);
+                        n++;
+                    }
+
+                    mode = MODE_NORMAL;
+                    break;
+                }
+                case 'p':
+                    _putchar('0');
+                    _putchar('x');
+                    n += 2;
+                case 'x':
+                    flags |= FLAG_LCHEX;
+                case 'X': {
+                    union {
+                        u64_t   u64[1];
+                        u32_t   u32[2];
+                        u16_t   u16[4];
+                        u8_t    u8[8];
+                    } value;
+                    char sstr[16];
+                    const char *alpha;
+                    int i, j;
+
+                    switch(size) {
+                        case 1:
+                            value.u8[7] = (u8_t)(*arg++ & 0xff);
+                            break;
+                        case 2:
+                            value.u16[3] = (u16_t)(*arg++ & 0xffff);
+                            break;
+                        case 0:
+                            size = 4;
+                        case 4:
+                            value.u32[1] = (u32_t)(*arg++ & 0xffffffff);
+                            break;
+                        case 8:
+                            value.u64[0] = *((u64_t*)arg);
+                            arg += 2;
+                            break;
+                        default:
+                            PANIC("Invalid argument width in format string\n");
+                    }
+                    alpha = (flags & FLAG_LCHEX) ? alpha_lc : alpha_uc;
+
+                    for(i = 7, j = 0; i >= (8 - size); i--) {
+                        sstr[j++] = alpha[(value.u8[i] >> 4) & 0xf];
+                        sstr[j++] = alpha[value.u8[i] & 0xf];
+                    }
+
+                    for(i = 0; sstr[i] == '0' && i < j; i++);
+
+                    if(flags & FLAG_PAD) {
+                        pad -= (j - i);
+
+                        while(pad-- > 0) {
+                            _putchar('0');
+                            n++;
+                        }
+                    }
+
+                    for(; i < j; i++) {
+                        _putchar(sstr[i]);
+                        n++;
+                    }
+
+                    mode = MODE_NORMAL;
+                    break;
+                }
+                case 's': {
+                    char *str;
+
+                    str = *arg ? (char*)*arg++ : (char*)nullstr;
+
+                    while((c = *str++)) {
+                        _putchar(c);
+                        n++;
+                    }
+
+                    mode = MODE_NORMAL;
+                    break;
+                }
+                default:
+                    mode = MODE_NORMAL;
+                    break;
+            }
+        } else {
+            _putchar(c);
+            n++;
+        }
+    }
+
+    #undef MODE_NORMAL
+    #undef MODE_CONV
+    #undef FLAG_SIGN
+    #undef FLAG_PAD
+    #undef FLAG_LCHEX
+
+    return(n);
+}
+
+void dbg_panic(const char *func, const char *file, i32_t line, const char *msg) {
+    /* vga_attrs = 0x0400; *//* VGA_FONT(VGA_RED) | VGA_BACKGROUND(VGA_BLACK); */
+    VGA_SET_FONT(VGA_RED);
+
+    dbg_printf("PANIC: Kernel bug in %s, %s:%u: %s\n", func, file, line, msg);
+
+    while(1) {
+        asm volatile("cli");
+        asm volatile("hlt");
+    }
+}
diff --git a/kernel/arch/debug.o b/kernel/arch/debug.o
new file mode 100644 (file)
index 0000000..2e59868
Binary files /dev/null and b/kernel/arch/debug.o differ
diff --git a/kernel/arch/defs.h b/kernel/arch/defs.h
new file mode 100644 (file)
index 0000000..bf52790
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * This file is part of the Corax operating system.
+ * Copyright (C) 2016 Matthias Kruk
+ *
+ * Corax is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Corax is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Corax.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DEFS_H
+#define __DEFS_H
+
+#include <config.h>
+
+#define SD_TYPE_CODE        0xc09a00
+#define SD_TYPE_DATA        0xc09200
+#define SD_TYPE_TSS         0x808900
+#define SD_TYPE_INT_GATE    0x8e00
+#define SD_TYPE_TASK_GATE   0x8500
+#define SD_TYPE_CALL_GATE   0x8c00
+#define SD_TYPE_TRAP_GATE   0x8f00
+
+#define DPL_KERNEL  0
+#define DPL_DRIVER  (1 << 13)
+#define DPL_SYSTEM  (2 << 13)
+#define DPL_USER    (3 << 13)
+
+#define RPL_KERNEL  0
+#define RPL_DRIVER  1
+#define RPL_SYSTEM  2
+#define RPL_USER    3
+
+#define KERNEL_DATA 0x10
+#define KERNEL_CODE 0x08
+
+#define USER_DATA   0x23
+#define USER_CODE   0x1b
+
+#define GDT_ENTRIES 16
+#define IDT_ENTRIES 256
+
+#define STACK0_SIZE CONFIG_KERNEL_STACK_SIZE
+#define STACK0_TOP  STACK0_SIZE
+#define GDT_OFFSET  STACK0_SIZE
+#define IDT_OFFSET  (GDT_OFFSET + (GDT_ENTRIES * 8))
+#define TSS_OFFSET  (IDT_OFFSET + (IDT_ENTRIES * 8))
+#define TSS_SIZE    102
+
+#define TSS_SEL     (0x28 | RPL_USER)
+
+#define CR0_PG_BIT      0x80000000
+#define CR4_PSE_BIT     0x00000010
+#define CR4_PAE_BIT     0x00000020
+
+#define PG_MODE_LEGACY      0x0
+#define PG_MODE_PAE         0x1
+#define PG_MODE_IA32E       0x2
+#define PG_MODE_INTEL64     0x3
+#define PG_MODE_MASK        0x3
+
+#define APIC_ID_ADDR    0xfee00020
+
+#if defined(CONFIG_APIC) && CONFIG_APIC == 1 && defined(__ASSEMBLY_SOURCE)
+
+.macro cpuidx r
+     movl APIC_ID_ADDR, \r
+        movl (\r), \r
+        shrl $24, \r
+.endm
+
+#else /* CONFIG_APIC */
+
+#if defined(CONFIG_SMP) && CONFIG_SMP == 1
+
+#error "SMP not yet implemented"
+
+#else /* CONFIG_SMP */
+
+#if defined(__ASSEMBLY_SOURCE)
+.macro cpuidx r
+        movl $0, \r
+.endm
+#endif
+
+#endif /* CONFIG_SMP */
+
+#endif /* CONFIG_APIC */
+
+#define EXC_VECTOR0         0x00
+#define INT_VECTOR0         0x40
+#define SYS_VECTOR0         0xCC
+
+#define NUM_EXC_VECTORS     21
+#if CONFIG_APIC == 1
+#define NUM_INT_VECTORS     24
+#else
+#define NUM_INT_VECTORS     16
+#endif /* CONFIG_APIC */
+#define NUM_SYS_VECTORS     1
+
+#define CORAX_SYS_VECTOR    0xCC
+
+/* i8259 definitions */
+#define PIC1_BASE           0x20
+#define PIC1_COMM           PIC1_BASE
+#define PIC1_DATA           (PIC1_BASE + 1)
+#define PIC2_BASE           0xA0
+#define PIC2_COMM           PIC2_BASE
+#define PIC2_DATA           (PIC2_BASE + 1)
+
+#define PIC1_VECTOR0        INT_VECTOR0
+#define PIC2_VECTOR0        (PIC1_VECTOR0 + 8)
+
+/* APIC definitions in apic.h */
+
+/* Intel-defined exception vectors */
+
+#define EXC(n)              (EXC_VECTOR0 + (n))
+#define EXC_DIVERR          EXC(0)
+#define EXC_DEBUG           EXC(1)
+#define EXC_NMI             EXC(2)
+#define EXC_BREAKPOINT      EXC(3)
+#define EXC_OVERFLOW        EXC(4)
+#define EXC_BOUNDRANGE      EXC(5)
+#define EXC_INVALOPCODE     EXC(6)
+#define EXC_DEVNOTAVAIL     EXC(7)
+#define EXC_DOUBLEFAULT     EXC(8)
+#define EXC_COPROCSEGM      EXC(9)
+#define EXC_INVALIDTSS      EXC(10)
+#define EXC_SEGMNOTPRES     EXC(11)
+#define EXC_STACKFAULT      EXC(12)
+#define EXC_PROTECTION      EXC(13)
+#define EXC_PAGEFAULT       EXC(14)
+/* Exception vector 15 is reserved */
+#define EXC_FPUERROR        EXC(16)
+#define EXC_ALIGNMENT       EXC(17)
+#define EXC_MACHINECHECK    EXC(18)
+#define EXC_SIMD            EXC(19)
+#define EXC_VIRTUALIZATION  EXC(20)
+#define EXC_MAX             EXC(21)
+
+/* Interrupt vectors */
+
+#define INT(n)              (INT_VECTOR0 + (n))
+#define INT_TIMER           INT(0)
+#define INT_KEYBOARD        INT(1)
+
+#if CONFIG_APIC == 1
+
+#define INT_APICERR         INT(-2)
+#define INT_SPURIOUS        INT(-1)
+/* what do we use INT 2 on APIC systems for? */
+#else
+/* on non-APIC systems, INT 2 is the cascaded i8259 PIC */
+#define INT_I8259           INT(2)
+#endif /* CONFIG_APIC */
+
+#define INT_FLOPPY          INT(3)
+#define INT_HARDDRIVE       INT(4)
+#define INT_RTC             INT(5)
+#define INT_HPET            INT(6) /* is it really? */
+#define INT_NETWORK         INT(7)
+#define INT_MAX             INT(8)
+
+/* definitions for tasks and task switching */
+
+#define STACK_OFFSET        8
+#define STACK_INIT_SIZE     56
+#define STACK_SIZE          CONFIG_USER_STACK_SIZE
+
+/* initial EFLAGS value for tasks */
+#define USER_EFLAGS         0x200
+
+/* EFLAGS fields:
+ * 0x1    = CF
+ * 0x2    = RESV (1)
+ * 0x4    = PF
+ * 0x8    = RESV (0)
+ * 0x10   = AF
+ * 0x20   = RESV (0)
+ * 0x40   = ZF
+ * 0x80   = SF
+ * 0x100  = TF
+ * 0x200  = IF
+ * 0x400  = DF
+ * 0x800  = OF
+ * 0x1000 = 
+ */
+#endif /* __DEFS_H */
diff --git a/kernel/arch/entry.S b/kernel/arch/entry.S
new file mode 100644 (file)
index 0000000..0603c6d
--- /dev/null
@@ -0,0 +1,343 @@
+/*
+ * This file is part of the Corax operating system.
+ * Copyright (C) 2016 Matthias Kruk
+ *
+ * Corax is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Corax is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Corax.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include "defs.h"
+
+.section .text
+
+.global _exc_entry0
+.global _exc_entry1
+.global _exc_entry2
+.global _exc_entry3
+.global _exc_entry4
+.global _exc_entry5
+.global _exc_entry6
+.global _exc_entry7
+.global _exc_entry8
+.global _exc_entry9
+.global _exc_entry10
+.global _exc_entry11
+.global _exc_entry12
+.global _exc_entry13
+.global _exc_entry14
+.global _exc_entry15
+.global _exc_entry16
+.global _exc_entry17
+.global _exc_entry18
+.global _exc_entry19
+.global _exc_entry20
+
+.global _int_entry0
+.global _int_entry1
+.global _int_entry2
+.global _int_entry3
+.global _int_entry4
+.global _int_entry5
+.global _int_entry6
+.global _int_entry7
+.global _int_entry8
+.global _int_entry9
+.global _int_entry10
+.global _int_entry11
+.global _int_entry12
+.global _int_entry13
+.global _int_entry14
+.global _int_entry15
+#if CONFIG_APIC == 1
+.global _int_entry16
+.global _int_entry17
+.global _int_entry18
+.global _int_entry19
+.global _int_entry20
+.global _int_entry21
+.global _int_entry22
+.global _int_entry23
+#endif /* CONFIG_APIC */
+
+.global _sys_entryCC
+
+.global _int_entry_common
+
+.extern _exc_handle
+.extern _int_handle
+.extern _sys_handle
+
+_exc_entry0:
+    pushl   $0
+    pushl   $EXC(0)
+    jmp     _int_entry_common
+
+_exc_entry1:
+    pushl   $0
+    pushl   $EXC(1)
+    jmp     _int_entry_common
+
+_exc_entry2:
+    pushl   $0
+    pushl   $EXC(2)
+    jmp     _int_entry_common
+
+_exc_entry3:
+    pushl   $0
+    pushl   $EXC(3)
+    jmp     _int_entry_common
+
+_exc_entry4:
+    pushl   $0
+    pushl   $EXC(4)
+    jmp     _int_entry_common
+
+_exc_entry5:
+    pushl   $0
+    pushl   $EXC(5)
+    jmp     _int_entry_common
+
+_exc_entry6:
+    pushl   $0
+    pushl   $EXC(6)
+    jmp     _int_entry_common
+
+_exc_entry7:
+    pushl   $0
+    pushl   $EXC(7)
+    jmp     _int_entry_common
+
+_exc_entry8:
+    pushl   $EXC(8)
+    jmp     _int_entry_common
+
+_exc_entry9:
+    pushl   $0
+    pushl   $EXC(9)
+    jmp     _int_entry_common
+
+_exc_entry10:
+    pushl   $EXC(10)
+    jmp     _int_entry_common
+
+_exc_entry11:
+    pushl   $EXC(11)
+    jmp     _int_entry_common
+
+_exc_entry12:
+    pushl   $EXC(12)
+    jmp     _int_entry_common
+
+_exc_entry13:
+    pushl   $EXC(13)
+    jmp     _int_entry_common
+
+_exc_entry14:
+    pushl   $EXC(14)
+    jmp     _int_entry_common
+
+_exc_entry15:
+    pushl   $0
+    pushl   $EXC(15)
+    jmp     _int_entry_common
+
+_exc_entry16:
+    pushl   $0
+    pushl   $EXC(16)
+    jmp     _int_entry_common
+
+_exc_entry17:
+    pushl   $EXC(17)
+    jmp     _int_entry_common
+
+_exc_entry18:
+    pushl   $0
+    pushl   $EXC(18)
+    jmp     _int_entry_common
+
+_exc_entry19:
+    pushl   $0
+    pushl   $EXC(19)
+    jmp     _int_entry_common
+
+_exc_entry20:
+    pushl   $0
+    pushl   $EXC(20)
+    jmp     _int_entry_common
+
+_int_entry0:
+    pushl   $0
+    pushl   $INT(0)
+    jmp     _int_entry_common
+
+_int_entry1:
+    pushl   $0
+    pushl   $INT(1)
+    jmp     _int_entry_common
+
+_int_entry2:
+    pushl   $0
+    pushl   $INT(2)
+    jmp     _int_entry_common
+
+_int_entry3:
+    pushl   $0
+    pushl   $INT(3)
+    jmp     _int_entry_common
+
+_int_entry4:
+    pushl   $0
+    pushl   $INT(4)
+    jmp     _int_entry_common
+
+_int_entry5:
+    pushl   $0
+    pushl   $INT(5)
+    jmp     _int_entry_common
+
+_int_entry6:
+    pushl   $0
+    pushl   $INT(6)
+    jmp     _int_entry_common
+
+_int_entry7:
+    pushl   $0
+    pushl   $INT(7)
+    jmp     _int_entry_common
+
+_int_entry8:
+    pushl   $0
+    pushl   $INT(8)
+    jmp     _int_entry_common
+
+_int_entry9:
+    pushl   $0
+    pushl   $INT(9)
+    jmp     _int_entry_common
+
+_int_entry10:
+    pushl   $0
+    pushl   $INT(10)
+    jmp     _int_entry_common
+
+_int_entry11:
+    pushl   $0
+    pushl   $INT(11)
+    jmp     _int_entry_common
+
+_int_entry12:
+    pushl   $0
+    pushl   $INT(12)
+    jmp     _int_entry_common
+
+_int_entry13:
+    pushl   $0
+    pushl   $INT(13)
+    jmp     _int_entry_common
+
+_int_entry14:
+    pushl   $0
+    pushl   $INT(14)
+    jmp     _int_entry_common
+
+_int_entry15:
+    pushl   $0
+    pushl   $INT(15)
+    jmp     _int_entry_common
+
+#if CONFIG_APIC == 1
+
+_int_entry16:
+    pushl   $0
+    pushl   $INT(16)
+    jmp     _int_entry_common
+
+_int_entry17:
+    pushl   $0
+    pushl   $INT(17)
+    jmp     _int_entry_common
+
+_int_entry18:
+    pushl   $0
+    pushl   $INT(18)
+    jmp     _int_entry_common
+
+_int_entry19:
+    pushl   $0
+    pushl   $INT(19)
+    jmp     _int_entry_common
+
+_int_entry20:
+    pushl   $0
+    pushl   $INT(20)
+    jmp     _int_entry_common
+
+_int_entry21:
+    pushl   $0
+    pushl   $INT(21)
+    jmp     _int_entry_common
+
+_int_entry22:
+    pushl   $0
+    pushl   $INT(22)
+    jmp     _int_entry_common
+
+_int_entry23:
+    pushl   $0
+    pushl   $INT(23)
+    jmp     _int_entry_common
+
+#endif /* CONFIG_APIC */
+
+_sys_entryCC:
+    pushl   $0
+    pushl   $SYS_VECTOR0
+
+_int_entry_common:
+    pusha
+    movw    %ds, %ax
+    pushl   %eax
+
+    movw    $KERNEL_DATA, %ax
+    movw    %ax, %ds
+    movw    %ax, %es
+    movw    %ax, %fs
+    movw    %ax, %gs
+
+    cmp     $EXC_MAX, 36(%esp)
+    jl      0f
+
+    cmp     $INT_MAX, 36(%esp)
+    jl      1f
+
+    call    _sys_handle
+    jmp     _int_restore
+
+    0:
+    call    _exc_handle
+    jmp     _int_restore
+
+    1:
+    call    _int_handle
+
+    _int_restore:
+    popl    %eax
+    movw    %ax, %ds
+    movw    %ax, %es
+    movw    %ax, %fs
+    movw    %ax, %gs
+
+    popa
+    add     $8, %esp
+    iret
diff --git a/kernel/arch/entry.o b/kernel/arch/entry.o
new file mode 100644 (file)
index 0000000..fb3c37a
Binary files /dev/null and b/kernel/arch/entry.o differ
diff --git a/kernel/arch/i8259.S b/kernel/arch/i8259.S
new file mode 100644 (file)
index 0000000..dce961a
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * This file is part of the Corax operating system.
+ * Copyright (C) 2016 Matthias Kruk
+ *
+ * Corax is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Corax is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Corax.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "defs.h"
+
+#define I8259_EOI   0x20
+
+.extern dbg_printf
+
+.section .text
+
+.global _i8259_init
+_i8259_init:
+    pushl   $_dbg_i8259
+    call    dbg_printf
+
+    /* TODO: initialise timer */
+/*  call    _i8259_getmask  */
+    xorl    %eax, %eax
+    movw    $0xfffd, %ax
+    movl    %eax, (%esp)
+    call    _i8259_setmask
+    addl    $4, %esp
+    sti
+    ret
+
+.global _i8259_getmask
+_i8259_getmask:
+    xorl    %eax, %eax
+    inb     $PIC2_DATA, %al
+    rorw    $8, %ax
+    inb     $PIC1_DATA, %al
+    ret
+
+.global _i8259_setmask
+_i8259_setmask:
+    movl    4(%esp), %eax
+    outb    %al, $PIC1_DATA
+    rorw    $8, %ax
+    outb    %al, $PIC2_DATA
+    ret
+
+.global _i8259_eoi
+_i8259_eoi:
+    movl    4(%esp), %eax
+    cmpl    $PIC1_VECTOR0, %eax
+    jl      1f
+    cmpl    $(PIC2_VECTOR0 + 7), %eax
+    jg      1f
+
+    cmpl    $PIC2_VECTOR0, %eax
+    movb    $I8259_EOI, %al
+    jl      2f
+
+    /* send EOI to cascaded PIC */
+    outb    %al, $PIC2_COMM
+
+    2:
+    /* send EOI to first PIC - we need to do this either way */
+    outb    %al, $PIC1_COMM
+
+    movl    $0, %eax
+    jmp     0f
+    1:
+    movl    $-1, %eax
+    0:
+    ret
+
+
+
+.section .data
+
+_dbg_i8259:
+    .asciz  "Initialising i8259 PIC\n"
diff --git a/kernel/arch/i8259.o b/kernel/arch/i8259.o
new file mode 100644 (file)
index 0000000..02d25b6
Binary files /dev/null and b/kernel/arch/i8259.o differ
diff --git a/kernel/arch/idle.S b/kernel/arch/idle.S
new file mode 100644 (file)
index 0000000..9f5d073
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the Corax operating system.
+ * Copyright (C) 2016 Matthias Kruk
+ *
+ * Corax is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Corax is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Corax.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "defs.h"
+
+_idle:
+    hlt
+    jmp _idle
diff --git a/kernel/arch/init.S b/kernel/arch/init.S
new file mode 100644 (file)
index 0000000..33ef2bf
--- /dev/null
@@ -0,0 +1,393 @@
+/*
+ * This file is part of the Corax operating system.
+ * Copyright (C) 2016 Matthias Kruk
+ *
+ * Corax is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Corax is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Corax.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include "defs.h"
+
+.global arch_init
+
+.extern _cpu
+.extern _segment_descriptor_set
+.extern _mem_start
+.extern _kernel_cr3
+.extern pg_init
+.extern dbg_printf
+
+.extern _i8259_init
+.extern _apic_init
+
+/* .extern memset */
+
+.extern _exc_entry0
+.extern _exc_entry1
+.extern _exc_entry2
+.extern _exc_entry3
+.extern _exc_entry4
+.extern _exc_entry5
+.extern _exc_entry6
+.extern _exc_entry7
+.extern _exc_entry8
+.extern _exc_entry9
+.extern _exc_entry10
+.extern _exc_entry11
+.extern _exc_entry12
+.extern _exc_entry13
+.extern _exc_entry14
+.extern _exc_entry15
+.extern _exc_entry16
+.extern _exc_entry17
+.extern _exc_entry18
+.extern _exc_entry19
+.extern _exc_entry20
+
+.extern _int_entry0
+.extern _int_entry1
+.extern _int_entry2
+.extern _int_entry3
+.extern _int_entry4
+.extern _int_entry5
+.extern _int_entry6
+.extern _int_entry7
+.extern _int_entry8
+.extern _int_entry9
+.extern _int_entry10
+.extern _int_entry11
+.extern _int_entry12
+.extern _int_entry13
+.extern _int_entry14
+.extern _int_entry15
+#if CONFIG_APIC == 1
+.extern _int_entry16
+.extern _int_entry17
+.extern _int_entry18
+.extern _int_entry19
+.extern _int_entry20
+.extern _int_entry21
+.extern _int_entry22
+.extern _int_entry23
+#endif /* CONFIG_APIC */
+
+.extern _sys_entryCC
+
+/* this table is used to fill the IDT in arch_init(),
+   saves us ~260B of memory, compared with an unrolled loop */
+.section .data
+_entries:
+    .long _exc_entry0
+    .long _exc_entry1
+    .long _exc_entry2
+    .long _exc_entry3
+    .long _exc_entry4
+    .long _exc_entry5
+    .long _exc_entry6
+    .long _exc_entry7
+    .long _exc_entry8
+    .long _exc_entry9
+    .long _exc_entry10
+    .long _exc_entry11
+    .long _exc_entry12
+    .long _exc_entry13
+    .long _exc_entry14
+    .long _exc_entry15
+    .long _exc_entry16
+    .long _exc_entry17
+    .long _exc_entry18
+    .long _exc_entry19
+    .long _exc_entry20
+    .long _int_entry0
+    .long _int_entry1
+    .long _int_entry2
+    .long _int_entry3
+    .long _int_entry4
+    .long _int_entry5
+    .long _int_entry6
+    .long _int_entry7
+    .long _int_entry8
+    .long _int_entry9
+    .long _int_entry10
+    .long _int_entry11
+    .long _int_entry12
+    .long _int_entry13
+    .long _int_entry14
+    .long _int_entry15
+#if CONFIG_APIC == 1
+    .long _int_entry16
+    .long _int_entry17
+    .long _int_entry18
+    .long _int_entry19
+    .long _int_entry20
+    .long _int_entry21
+    .long _int_entry22
+    .long _int_entry23
+#endif /* CONFIG_APIC */
+
+.section .text
+arch_init:
+    subl    $24, %esp
+
+    movl    $_mem_start, %eax
+    addl    $4, %eax
+    movl    %eax, (_mem_start)
+/*
+    movl    $_cpu, %eax
+    addl    $GDT_OFFSET, %eax
+    movl    %eax, (%esp)
+    movl    $0, 4(%esp)
+    movl    $GDT_ENTRIES, %eax
+    shll    $3, %eax
+    movl    %eax, 8(%esp)
+    call    memset
+
+    movl    $_cpu, %eax
+    addl    $IDT_OFFSET, %eax
+    movl    %eax, (%esp)
+    movl    $IDT_ENTRIES, %eax
+    shll    $3, %eax
+    movl    %eax, 8(%esp)
+    call    memset
+*/
+    movl    $_cpu, %eax
+    addl    $GDT_OFFSET, %eax
+    movl    $0, (%eax)
+    movl    $0, 4(%eax)
+    addl    $8, %eax
+
+    movl    $DPL_KERNEL, 16(%esp)
+    movl    $0xffffffff, 12(%esp)
+    movl    $0, 8(%esp)
+    movl    $SD_TYPE_CODE, 4(%esp)
+    movl    %eax, (%esp)
+    call    _segment_descriptor_set
+
+    movl    $SD_TYPE_DATA, 4(%esp)
+    addl    $8, (%esp)
+    call    _segment_descriptor_set
+
+    movl    $DPL_USER, 16(%esp)
+    addl    $16, (%esp)
+    call    _segment_descriptor_set
+
+    movl    $SD_TYPE_CODE, 4(%esp)
+    subl    $8, (%esp)
+    call    _segment_descriptor_set
+
+    addl    $16, (%esp)
+    movl    $SD_TYPE_TSS, 4(%esp)
+    movl    $_cpu, %eax
+    addl    $TSS_OFFSET, %eax
+    movl    %eax, 8(%esp)
+    movl    $TSS_SIZE, 12(%esp)
+    call    _segment_descriptor_set
+
+    movw    $GDT_ENTRIES, %ax
+    shlw    $3, %ax
+    addw    $1, %ax
+    movw    %ax, (%esp)
+    movl    $_cpu, %eax
+    addl    $GDT_OFFSET, %eax
+    movl    %eax, 2(%esp)
+    lgdt    (%esp)
+
+    movw    $KERNEL_DATA, %ax
+    movw    %ax, %ds
+    movw    %ax, %es
+    movw    %ax, %fs
+    movw    %ax, %gs
+    movw    %ax, %ss
+    ljmp    $KERNEL_CODE, $_update_cs
+    .local _update_cs
+    _update_cs:
+
+    movw    $TSS_SEL, %ax
+    ltr     %ax
+
+    /* according to osdev.org, it is necessary to mask all
+     * i8259 channels and remap them when we're using APIC,
+     * but according to Intel documentation, the i8259, or
+     * whatever compatibility circuit is left of it, should
+     * be completely disconnected from the CPU's INTR line
+     * as soon as we're setting the IMCR to 1 */
+
+    /* mask all i8259 channels */
+    mov     $0xff, %al
+    outb    %al, $PIC1_DATA
+    outb    %al, $PIC2_DATA
+
+    /* remap i8259 interrupts */
+    movb    $0x11, %al
+    outb    %al, $PIC1_COMM
+    outb    %al, $PIC2_COMM
+    movb    $PIC1_VECTOR0, %al
+    outb    %al, $PIC1_DATA
+    movb    $PIC2_VECTOR0, %al
+    outb    %al, $PIC2_DATA
+    movb    $0x04, %al
+    outb    %al, $PIC1_DATA
+    movb    $0x02, %al
+    outb    %al, $PIC2_DATA
+    movb    $0x01, %al
+    outb    %al, $PIC1_DATA
+    outb    %al, $PIC2_DATA
+    xorl    %eax, %eax
+    outb    %al, $PIC1_DATA
+    outb    %al, $PIC2_DATA
+
+    xorl    %esi, %esi
+    movl    $_cpu, %edi
+    addl    $IDT_OFFSET, %edi
+
+    movl    $DPL_USER, 16(%esp)
+    movl    $8, 8(%esp)
+    movl    $SD_TYPE_INT_GATE, 4(%esp)
+    movl    %edi, (%esp)
+
+    0:
+    cmpl    $(NUM_EXC_VECTORS + NUM_INT_VECTORS), %esi
+    jge     1f
+
+    cmpl    $NUM_EXC_VECTORS, %esi
+    jnz     2f
+    addl    $((INT_VECTOR0 - NUM_EXC_VECTORS) * 8), (%esp)
+    2:
+
+    movl    _entries(,%esi,4), %eax
+    movl    %eax, 12(%esp)
+    call    _segment_descriptor_set
+    addl    $8, (%esp)
+    addl    $1, %esi
+    jmp     0b
+    1:
+
+    /*
+    _idt_fill:
+    movl    20(%esp), %ecx
+    cmpl    $(INT_VECTORS + NUM_INT_VECTORS), %ecx
+    jge     _idt_fill_done
+
+    cmpl    $NUM_EXC_VECTORS, %ecx
+    jne     _skip_adjust
+    addl    $0x60, (%esp)
+    _skip_adjust:
+
+    movl    _entries(,%ecx,4), %eax
+    movl    %eax, 12(%esp)
+    addl    $1, %ecx
+    movl    %ecx, 20(%esp)
+    call    _segment_descriptor_set
+    addl    $8, (%esp)
+    jmp     _idt_fill
+    _idt_fill_done:
+    */
+
+    /* add an entry for Corax syscalls */
+    movl    $_sys_entryCC, 12(%esp)
+    addl    $((SYS_VECTOR0 - (INT_VECTOR0 + NUM_INT_VECTORS)) * 8), (%esp)
+    call    _segment_descriptor_set
+
+    movw    $((IDT_ENTRIES * 8) + 1), (%esp)
+    movl    $_cpu, %eax
+    addl    $IDT_OFFSET, %eax
+    movl    %eax, 2(%esp)
+    lidt    (%esp)
+
+    addl    $24, %esp
+    movl    4(%esp), %eax
+    pushl   %eax
+    call    pg_init
+    addl    $4, %esp
+
+    movl    %eax, %ebx
+    andl    $0xffffffe0, %eax
+
+    test    %eax, %eax
+    jz      0f
+
+    movl    %eax, %cr3
+
+    andl    $PG_MODE_MASK, %ebx
+    cmp     $PG_MODE_LEGACY, %ebx
+    jz      1f
+
+    /* FIXME: what about IA-32e mode? */
+
+    movl    %cr4, %eax
+    orl     $CR4_PAE_BIT, %eax
+    movl    %eax, %cr4
+
+    1: /* legacy paging */
+    movl    %cr4, %eax
+    orl     $CR4_PSE_BIT, %eax
+    movl    %eax, %cr4
+
+    movl    %cr0, %eax
+    orl     $CR0_PG_BIT, %eax
+    movl    %eax, %cr0
+
+    movl    $0, %eax
+    jmp     2f
+    0: /* failure or no paging */
+    movl    $-1, %eax
+    2:
+
+    pushl   %eax
+#if CONFIG_APIC == 1
+    movl    $1, %eax
+    cpuid
+    test    $0x200, %edx
+    jz      0f
+    call    _apic_init
+
+    jmp     1f
+    0:
+#endif /* CONFIG_APIC */
+    call    _i8259_init
+    1:
+
+    popl    %ebx
+    orl     %eax, %ebx
+/*
+    subl    $16, %esp
+    movl    %eax, 12(%esp)
+    movl    %cr0, %eax
+    movl    %eax, 8(%esp)
+    movl    $0, 4(%esp)
+    movl    $_pg_dbg_crN, (%esp)
+    call    dbg_printf
+
+    movl    %cr3, %eax
+    movl    %eax, 8(%esp)
+    movl    $3, 4(%esp)
+    call    dbg_printf
+
+    movl    %cr4, %eax
+    movl    %eax, 8(%esp)
+    movl    $4, 4(%esp)
+    call    dbg_printf
+
+    movl    12(%esp), %eax
+    addl    $16, %esp
+*/
+
+    sti
+    ret
+
+/*
+.section .data
+_pg_dbg_crN:
+    .asciz  "CR%u = 0x%08x\n"
+*/
diff --git a/kernel/arch/init.o b/kernel/arch/init.o
new file mode 100644 (file)
index 0000000..fa77260
Binary files /dev/null and b/kernel/arch/init.o differ
diff --git a/kernel/arch/interrupt.c b/kernel/arch/interrupt.c
new file mode 100644 (file)
index 0000000..49d3768
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * This file is part of the Corax operating system.
+ * Copyright (C) 2016 Matthias Kruk
+ *
+ * Corax is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Corax is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Corax.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <corax/types.h>
+#include <debug.h>
+#include "cpu.h"
+#include "defs.h"
+
+static const char *_exc_name[] = {
+    "#DE", "#DB", "NMI", "#BP", "#OF", "#BR", "#UD", "#NM", "#DF", "#MF",
+    "#TS", "#NP", "#SS", "#GP", "#PF", "RESV", "#MF", "#AC", "#MC", "#XM",
+    "#VE"
+};
+
+#if CONFIG_APIC == 1
+extern void _apic_eoi(u32_t);
+#else
+extern void _i8259_eoi(u32_t);
+#endif /* CONFIG_APIC */
+
+int _int_handle(stack_frame_t ctx)
+{
+    switch(ctx.intn) {
+#if CONFIG_APIC == 1
+       case INT_APICERR:
+               dbg_printf("APIC Error: 0x%08x\n", ctx.error);
+               break;
+       case INT_SPURIOUS:
+               dbg_printf("Spurious interrupt\n");
+               break;
+#endif /* CONFIG_APIC */
+       default:
+               break;
+    }
+/*
+    if(ctx.intn == 32) {
+        unsigned *apic_esr;
+        unsigned apic_err;
+
+        apic_esr = (unsigned*)0xfee00280;
+        apic_err = *apic_esr;
+
+        dbg_printf("APIC ESR: 0x%08x\n", apic_err);
+    }
+    */
+/*    PANIC("Unhandled interrupt"); */
+
+    if(ctx.intn == INT_KEYBOARD) {
+        extern struct cpu _cpu[CONFIG_SMP_CPUS];
+
+        dbg_printf("Rebooting...\n");
+
+        /* hacky reboot: clear IDT entries for
+         * #DF and #GP, then cause a #GP */
+        _cpu[CPU_ID].cpu_idt[EXC_DOUBLEFAULT].sd_low = 0;
+        _cpu[CPU_ID].cpu_idt[EXC_DOUBLEFAULT].sd_high = 0;
+        _cpu[CPU_ID].cpu_idt[EXC_PROTECTION].sd_low = 0;
+        _cpu[CPU_ID].cpu_idt[EXC_PROTECTION].sd_high = 0;
+
+        /* this is such a retarded thing to do, I don't see how this
+         * could not cause a triple fault */
+        asm volatile("ljmp $0x30, $0xfee00020"); /* LEEROY JENKINS!!! */
+    } else if(ctx.intn != INT_TIMER) {
+               dbg_printf("Interrupt %u occurred\n", ctx.intn);
+       }
+
+    #if CONFIG_APIC == 1
+    /* FIXME: Make sure this is NOT done for NMI, SMI, INIT, ExtInt,
+     * SIPI or INIT-deassert mode interrupts */
+    _apic_eoi(ctx.intn);
+    #else
+    _i8259_eoi(ctx.intn);
+    #endif /* CONFIG_APIC */
+
+    return(0);
+}
+
+int _exc_handle(stack_frame_t ctx)
+{
+    dbg_printf("Exception %u [%s] occurred. Error code 0x%08x.\n", ctx.intn, ctx.intn < EXC_MAX ? _exc_name[ctx.intn] : 0, ctx.error);
+    dbg_printf("Fault in 0x%02x:%08x; EFLAGS = 0x%08x\n", ctx.cs, ctx.eip, ctx.eflags);
+
+    if(ctx.intn == EXC_PAGEFAULT) {
+        u32_t cr2;
+
+        asm volatile("movl %%cr2, %%eax; movl %%eax, %0" : "=r"(cr2));
+        dbg_printf("Page fault address: 0x%08x\n", cr2);
+    }
+
+    PANIC("Unhandled exception");
+
+    return(0);
+}
+
+int _sys_handle(stack_frame_t ctx) {
+/*  dbg_printf("Syscall 0x%X occurred.\n", ctx.intn);   */
+/*  dbg_printf("CS = 0x%02x; EIP = 0x%08x; EFLAGS = 0x%08x\n", ctx.cs, ctx.eip, ctx.eflags); */
+/*  PANIC("Unhandled syscall");   */
+
+       dbg_printf("_corax_call(0x%x, 0x%x, 0x%x);\n", ctx.eax, ctx.ebx, ctx.ecx);
+
+    return(0);
+}
diff --git a/kernel/arch/interrupt.o b/kernel/arch/interrupt.o
new file mode 100644 (file)
index 0000000..c3b4f2b
Binary files /dev/null and b/kernel/arch/interrupt.o differ
diff --git a/kernel/arch/paging.c b/kernel/arch/paging.c
new file mode 100644 (file)
index 0000000..e3c9712
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ * This file is part of the Corax operating system.
+ * Copyright (C) 2016 Matthias Kruk
+ *
+ * Corax is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Corax is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Corax.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <corax/types.h>
+#include <multiboot.h>
+#include <debug.h>
+#include "cpu.h"
+#include "paging.h"
+
+#define _frame_set(addr)    _frame_map[(addr) >> 17] |= 1 << (((addr) >> 12) & 0x1f)
+#define _frame_clear(addr)  _frame_map[(addr) >> 17] &= ~(1 << (((addr) >> 12) & 0x1f))
+
+extern u32_t _mem_start;
+
+static u32_t _kernel_cr3 = 0;
+static u32_t _pg_flags = 0;
+static u32_t *_frame_map;
+static u32_t _nframes;
+
+static void* _phys_alloc(u32_t, u32_t);
+
+static const char *_str_pg_mode[] = {
+    "legacy IA-32 mode",
+    "PAE mode",
+    "IA-32e mode",
+    "Intel64 mode"
+};
+
+void* pg_dir_create(void) {
+    void *dir;
+
+    dir = NULL;
+
+    if(!_kernel_cr3) {
+        dir = _phys_alloc(sizeof(pdpt_t), PDPT_ALIGN);
+    } else {
+
+    }
+
+    return(dir);
+}
+
+static void* _phys_alloc(u32_t size, u32_t align) {
+    extern u32_t _mem_start;
+    void *addr;
+
+    addr = NULL;
+
+    if(align) {
+        /* check if address needs alignment */
+        if(_mem_start & (align - 1)) {
+            _mem_start = (_mem_start & ~(align - 1)) + align;
+        }
+    }
+
+    addr = (void*)_mem_start;
+    _mem_start += size;
+
+    memset(addr, 0, size);
+
+    return(addr);
+}
+
+void* pg_init(struct multiboot_info *info) {
+    struct memory_map *mmap;
+    u64_t mem_size;
+    u64_t map_end;
+    u64_t mapped;
+    u32_t cr3;
+    u32_t i;
+
+    /* TODO: Clean up a little in here... */
+
+    _mem_start = (u32_t)&_mem_start + sizeof(u32_t);
+    mmap = (struct memory_map*)info->mmap_addr;
+    mem_size = 0;
+
+    /* TODO: get rid of this */
+    while((u32_t)mmap < (info->mmap_addr + info->mmap_length)) {
+        mem_size += mmap->len;
+        mmap = (struct memory_map*)((u32_t)mmap + mmap->size + sizeof(mmap->size));
+    }
+
+    /* FIXME: memory size is not good evidence of PAE capability */
+
+    if(mem_size < 0x100000000L) {
+        /* we have less than 4G of memory, no need for PAE */
+        _pg_flags = PG_MODE_LEGACY;
+        map_end = mem_size;
+    } else {
+        /* TODO: check if IA-32e paging is supported */
+        _pg_flags = PG_MODE_PAE;
+        map_end = 0x100000000L;
+    }
+    mapped = 0;
+
+    /* FIXME: We're including memory holes between regions in the calculation.
+     * This WILL not end well */
+    _nframes = mem_size >> 17;
+    _frame_map = _phys_alloc(_nframes << 2, 4);
+
+    switch(_pg_flags & PG_MODE_MASK) {
+        case PG_MODE_LEGACY: {
+            cr3 = (u32_t)_phys_alloc(sizeof(page_table_t), PAGE_ALIGN);
+            break;
+        }
+        case PG_MODE_PAE:
+            cr3 = (u32_t)_phys_alloc(sizeof(pdpt_t), PDPT_ALIGN);
+            break;
+        case PG_MODE_INTEL64:
+        case PG_MODE_IA32E:
+            PANIC("IA-32e mode paging not yet supported\n");
+    }
+
+    mmap = (struct memory_map*)info->mmap_addr;
+    while((u32_t)mmap < (info->mmap_addr + info->mmap_length)) {
+        u32_t attrs;
+        u64_t addr;
+/*
+        dbg_printf("Region: 0x%016llx - 0x%016llx [%u]\n", mmap->addr, mmap->addr + mmap->len, mmap->type);
+*/
+        attrs = PAGE_ATTR_SIZE | PAGE_ATTR_WRITABLE | PAGE_ATTR_PRESENT;
+
+        /* disable caching on reserved memory areas */
+        if(mmap->type != MEM_AVAILABLE) {
+            attrs |= PAGE_ATTR_WRITE_THRU | PAGE_ATTR_CACHE_DISABLE;
+
+            /* mark page frames in this region as used */
+            for(addr = mmap->addr; addr < (mmap->addr + mmap->len); addr += PAGE_SIZE) {
+                _frame_set(addr);
+            }
+        }
+
+        switch(_pg_flags & PG_MODE_MASK) {
+            case PG_MODE_LEGACY: {
+                page_table_t *pd;
+
+                pd = (page_table_t*)cr3;
+
+                for(addr = mmap->addr & ~(PAGE_SIZE_LARGE - 1); addr < (mmap->addr + mmap->len); addr += PAGE_SIZE_LARGE) {
+                    pd->pt_entries[addr >> 22] = (u32_t)addr | attrs;
+                }
+
+                break;
+            }
+            case PG_MODE_PAE: {
+                pdpt_t *pd;
+
+                pd = (pdpt_t*)cr3;
+
+                /* the way PAE works we can access 64G of physical memory, but we can still
+                 * only address 4G at a time, i.e. in each page directory. So stop at 4G. */
+                for(addr = mmap->addr & ~(PAGE_SIZE_BIG - 1); addr < (mmap->addr + mmap->len) && addr < 0x100000000LL; addr += PAGE_SIZE_BIG) {
+                    pae_page_table_t *pt;
+
+                    if(!pd->pdpt_entries[(addr >> 30) & 0x3]) {
+                        pt = (pae_page_table_t*)_phys_alloc(PAGE_SIZE, PAGE_ALIGN);
+                        pd->pdpt_entries[(addr >> 30) & 0x3] = (u32_t)pt | PAGE_ATTR_PRESENT;
+                    } else {
+                        /* FIXME: I'm pretty sure this will break on Intel64 */
+                        pt = (pae_page_table_t*)((u32_t)pd->pdpt_entries[(addr >> 30) & 0x3] ^ 0x1);
+                    }
+
+                    pt->ppt_entries[(addr >> 21) & 0x1ff] = addr | attrs;
+                }
+                break;
+            }
+            case PG_MODE_INTEL64:
+            case PG_MODE_IA32E:
+                PANIC("How did I get here?");
+        }
+        mmap = (struct memory_map*)((u32_t)mmap + mmap->size + sizeof(mmap->size));
+    }
+    /*
+    switch(_pg_flags & PG_MODE_MASK) {
+        default:
+            _pg_flags = PG_MODE_LEGACY;
+        case PG_MODE_LEGACY: {
+            page_table_t *pt;
+
+            pt = (page_table_t*)_phys_alloc(PAGE_SIZE, PAGE_ALIGN);
+
+            while(mapped < map_end) {
+                pt->pt_entries[mapped >> 22] = (u32_t)mapped | PAGE_ATTR_SIZE | PAGE_ATTR_WRITABLE | PAGE_ATTR_PRESENT;
+                mapped += PAGE_SIZE_LARGE;
+            }
+
+            cr3 = (u32_t)pt;
+            break;
+        }
+        case PG_MODE_PAE: {
+            pdpt_t *pd;
+            pae_page_table_t *pt;
+
+            pd = (pdpt_t*)_phys_alloc(sizeof(pdpt_t), PDPT_ALIGN);
+
+            while(mapped < map_end) {
+                if(!(mapped & (PAGE_SIZE_HUGE - 1))) {
+                    pt = (pae_page_table_t*)_phys_alloc(PAGE_SIZE, PAGE_ALIGN);
+                    pd->pdpt_entries[(mapped >> 30) & 0x3] = (u32_t)pt | PAGE_ATTR_PRESENT;
+                }
+
+                pt->ppt_entries[(mapped >> 21) & 0x1ff] = mapped | PAGE_ATTR_SIZE | PAGE_ATTR_WRITABLE | PAGE_ATTR_PRESENT;
+                mapped += PAGE_SIZE_BIG;
+            }
+
+            cr3 = (u32_t)pd;
+            break;
+        }
+        case PG_MODE_INTEL64:
+        case PG_MODE_IA32E: {
+            PANIC("IA-32e mode paging not yet supported\n");
+            break;
+        }
+    }
+    */
+    /* mark all page frames from 0x0 to the end of the last kernel page dir/table as used */
+
+    for(i = 0; i < _mem_start; i += PAGE_SIZE) {
+        _frame_set(i);
+    }
+
+    /* mark frames in reserved areas from GRUB-provided memory map as used and not-cachable */
+    /*
+    mmap = (struct memory_map*)info->mmap_addr;
+    while((u32_t)mmap < (info->mmap_addr + info->mmap_length)) {
+        if(mmap->type != MEM_AVAILABLE) {
+            u64_t addr;
+
+            for(addr = mmap->addr; addr < (mmap->addr + mmap->len); addr += PAGE_SIZE) {
+                _frame_set(addr);
+
+                if(!(addr & (PAGE_SIZE_BIG - 1))) {
+                    switch(_pg_flags & PG_MODE_MASK) {
+                        case PG_MODE_LEGACY:
+                            ((page_table_t*)cr3)->pt_entries[addr >> 22] |= PAGE_ATTR_CACHE_DISABLE | PAGE_ATTR_WRITE_THRU;
+                            break;
+                        case PG_MODE_PAE: {
+                            pae_page_table_t *pt;
+
+                            pt = (pae_page_table_t*)((u32_t)((pdpt_t*)cr3)->pdpt_entries[(addr >> 30) & 0x3] ^ 0x1);
+                            pt->ppt_entries[(addr >> 21) & 0x1ff] |= PAGE_ATTR_CACHE_DISABLE | PAGE_ATTR_WRITE_THRU;
+                            break;
+                        }
+                        default:
+                        case PG_MODE_IA32E:
+                        case PG_MODE_INTEL64:
+                            PANIC("IA-32e mode paging not yet supported\n");
+                    }
+                }
+            }
+        }
+
+        mmap = (struct memory_map*)((u32_t)mmap + mmap->size + sizeof(mmap->size));
+    }
+    */
+    _kernel_cr3 = (u32_t)cr3;
+
+    dbg_printf("Enabling %s paging\n", _str_pg_mode[_pg_flags & 0x3]);
+
+    return((void*)(cr3 | _pg_flags));
+}
diff --git a/kernel/arch/paging.h b/kernel/arch/paging.h
new file mode 100644 (file)
index 0000000..a44080e
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * This file is part of the Corax operating system.
+ * Copyright (C) 2016 Matthias Kruk
+ *
+ * Corax is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Corax is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Corax.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __PAGING_H
+#define __PAGING_H
+
+#include <corax/types.h>
+#include "defs.h"
+
+typedef struct pdpt pdpt_t;
+
+struct pdpt {
+    u64_t   pdpt_entries[4];
+} __attribute__((packed));
+
+typedef struct pae_page_table pae_page_table_t;
+typedef struct page_table page_table_t;
+
+struct page_table {
+    u32_t pt_entries[1024];
+} __attribute__((packed));
+
+struct pae_page_table {
+    u64_t ppt_entries[512];
+} __attribute__((packed));
+
+#define PDPT_ALIGN          32
+#define PAGE_ALIGN          0x1000
+
+#define PAGE_SIZE           0x1000
+#define PAGE_SIZE_BIG       0x200000
+#define PAGE_SIZE_LARGE     0x400000
+#define PAGE_SIZE_HUGE      0x40000000
+
+#define PAGE_ATTR_PRESENT           (1 << 0)
+#define PAGE_ATTR_WRITABLE          (1 << 1)
+#define PAGE_ATTR_USER              (1 << 2)
+#define PAGE_ATTR_WRITE_THRU        (1 << 3)
+#define PAGE_ATTR_CACHE_DISABLE     (1 << 4)
+#define PAGE_ATTR_ACCESSED          (1 << 5)
+#define PAGE_ATTR_DIRTY             (1 << 6)
+#define PAGE_ATTR_SIZE              (1 << 7)
+#define PAGE_ATTR_GLOBAL            (1 << 8)
+#define PAGE_ATTR_NO_EXEC           (1 << 63)
+
+#endif /* __PAGING_H */
diff --git a/kernel/arch/paging.o b/kernel/arch/paging.o
new file mode 100644 (file)
index 0000000..7e5594c
Binary files /dev/null and b/kernel/arch/paging.o differ
diff --git a/kernel/arch/task.S b/kernel/arch/task.S
new file mode 100644 (file)
index 0000000..caf5d12
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * This file is part of the Corax operating system.
+ * Copyright (C) 2016 Matthias Kruk
+ *
+ * Corax is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Corax is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Corax.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define __ASSEMBLY_SOURCE
+       
+#include <config.h>
+#include "defs.h"
+
+.extern _cpu
+
+.global _task_prepare
+_task_prepare:
+    pushl   %ebx
+    /* eax = task, ecx = eip, ebx = esp */
+    movl    8(%esp), %eax
+    movl    12(%esp), %ecx
+    movl    16(%esp), %ebx
+
+    addl    $(STACK_OFFSET + STACK_SIZE - STACK_INIT_SIZE), %eax
+    movl    $USER_DATA, (%eax)
+#if CONFIG_INITIALIZE_USER_REGS == 1
+    movl    $32, %esi
+    xorl    %edx, %edx
+
+0:     test    %esi, %esi
+    jz      1f
+    movl    %edx, (%eax, %esi)
+    subl    $4, %esi
+    jmp     0b
+
+#endif /* CONFIG_INITIALIZE_USER_REGS */
+    /* 4(%eax) - 32(%eax) is the location of the general purpose registers */
+1:     movl    %ecx, 36(%eax)
+    movl    $USER_CODE, 40(%eax)
+    movl    $USER_EFLAGS, 44(%eax)
+    movl    %ebx, 48(%eax)
+    movl    $USER_DATA, 52(%eax)
+
+    popl    %ebx
+    ret
+
+.global _task_switch
+_task_switch:
+    movl    4(%esp), %eax
+    movl    4(%eax), %ebx
+    movl    %cr3, %edx
+    cmpl    %edx, %ebx
+    jz      0f
+    movl    %ebx, %cr3
+
+0:     cpuidx  %ecx
+    movl    $CPU_SIZE, %esi
+    shll    %cl, %esi
+    movl    _cpu(%esi), %ebx
+    movl    CUR_TASK(%ebx), %edi
+    cmpl    %edi, %eax
+
+    jz      0b
+    movl    %esp, (%edi)
+    movl    %eax, CUR_TASK(%ebx)
+    movl    (%eax), %esp
+    iret
diff --git a/kernel/arch/task.h b/kernel/arch/task.h
new file mode 100644 (file)
index 0000000..0cd1fd2
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the Corax operating system.
+ * Copyright (C) 2016 Matthias Kruk
+ *
+ * Corax is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Corax is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Corax.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TASK_H
+#define __TASK_H
+
+#include <config.h>
+
+/* Definition of an architectural task - think of it
+ * as a TCB. It is not a operating system process or
+ * thread, but merely the information needed by the
+ * CPU to perform context switches, etc.
+ *
+ * Specifically, we need to remember the task's page
+ * directory and the stack pointer. The task's context
+ * is on top of its stack, i.e. all we have to do is
+ * load the task's stack pointer and execute an iret */
+
+struct task {
+    u32_t   t_esp;
+    u32_t   t_cr3;
+
+    u8_t    t_kstack[CONFIG_USER_STACK_SIZE];
+} __attribute__((packed));
+
+struct task* _task_prepare(struct task *t, u32_t eip, u32_t esp);
+void _task_switch(struct task*);
+
+#endif /* __TASK_H */
diff --git a/kernel/arch/task.o b/kernel/arch/task.o
new file mode 100644 (file)
index 0000000..9e4cd05
Binary files /dev/null and b/kernel/arch/task.o differ
diff --git a/kernel/core/Makefile b/kernel/core/Makefile
new file mode 100644 (file)
index 0000000..92db6f9
--- /dev/null
@@ -0,0 +1,15 @@
+OBJECTS = main.o
+OUTPUT = core.o
+INCLUDES = -I../include -I../../include -I../..
+CFLAGS += $(INCLUDES)
+PHONY = clean
+
+all: $(OUTPUT)
+
+$(OUTPUT): $(OBJECTS)
+       ld -r $(LDFLAGS) -o $@ $^
+
+clean:
+       rm -f $(OBJECTS) $(OUTPUT)
+
+.PHONY: $(PHONY)
diff --git a/kernel/core/core.o b/kernel/core/core.o
new file mode 100644 (file)
index 0000000..3fb2790
Binary files /dev/null and b/kernel/core/core.o differ
diff --git a/kernel/core/main.c b/kernel/core/main.c
new file mode 100644 (file)
index 0000000..85e8641
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * This file is part of the Corax operating system.
+ * Copyright (C) 2016 Matthias Kruk
+ *
+ * Corax is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Corax is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Corax.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <corax/types.h>
+#include <debug.h>
+#include <arch.h>
+#include "../arch/task.h"
+
+void cpu_debug(void);
+
+u8_t _stack[1024];
+
+void _idle(void)
+{
+       while(1) {
+               asm volatile("hlt");
+       }
+
+       return;
+}
+
+void _print_mptbl(void *tbl)
+{
+       u32_t *pmcp;
+       u16_t entries;
+
+       dbg_printf("MP: 0x%08x [0x%08x]\n", (u32_t)tbl, *(u32_t*)tbl);
+
+       pmcp = (u32_t*)*(u32_t*)(tbl + 4);
+
+       if(*pmcp == 0x504d4350 || *pmcp == 0x50434d50) {
+               entries = *(u16_t*)(pmcp + 1);
+
+               dbg_printf("PMCP: 0x%08x, l: %hu, [0x%08x]\n", pmcp, entries, *pmcp);
+               tbl += 0x2c;
+
+               while(entries) {
+                       u8_t type;
+
+                       type = *(u8_t*)tbl;
+
+                       switch(type) {
+                       case 0: /* processor entry */
+                               tbl += 0x14;
+                               break;
+                       case 1: /* bus entry */
+                               tbl += 8;
+                               break;
+                       case 2: /* IO APIC entry */
+                               tbl += 8;
+                               break;
+                       case 3: /* IO Interrupt entry */
+                               dbg_printf("[INT] T: 0x%02hhx SRC: 0x%02hhx IRQ: 0x%02hhx DEST: 0x%02hhx DINT: 0x%02hhx\n", *((u8_t*)tbl + 1), *((u8_t*)tbl + 4), *((u8_t*)tbl + 5), *((u8_t*)tbl + 6), *((u8_t*)tbl + 7));
+                               tbl += 8;
+                               break;
+                       case 4: /* Local Interrupt assignment entry */
+                               tbl += 8;
+                               break;
+                       default:
+                               dbg_printf("Unsupported entry\n");
+                               entries = 1;
+                               break;
+                       }
+
+                       entries--;
+               }
+       }
+
+       return;
+}
+
+int corax(void *mb_info, u32_t magic) {
+    dbg_printf("Corax 0.1 - As the Crow flies\n");
+    dbg_printf("(C) 2018 Matthias Kruk <matt@corax.cc>\n");
+    dbg_printf("Compiled on %s at %s\n", __DATE__, __TIME__);
+
+       u32_t p;
+/*
+    volatile register u64_t sysenter, sysexit;
+       void *ptr;
+
+       for(ptr = (void*)0xd0000; ptr < (void*)0xffffd; ptr++) {
+               if(*(u32_t*)ptr == 0x5f504d5f || *(u32_t*)ptr == 0x5f4d505f) {
+                       _print_mptbl(ptr);
+               }
+       }
+
+       for(ptr = (void*)0x9fc00; ptr <= (void*)0x9fffc; ptr++) {
+               if(*(u32_t*)ptr == 0x5f504d5f || *(u32_t*)ptr == 0x5f4d505f) {
+                       _print_mptbl(ptr);
+               }
+       }
+
+       for(ptr = NULL; ptr <= (void*)0x1000000; ptr++) {
+               if(*(u32_t*)ptr == 0x5f504d5f || *(u32_t*)ptr == 0x5f4d505f) {
+                       _print_mptbl(ptr);
+               }
+       }
+       */
+/*     void *ptr;*/
+
+    arch_init(mb_info);
+/*
+    u64_t capabilities = cpu_get_capabilities();
+    dbg_printf("CPUID.01h = 0x%016llx\n", capabilities);
+
+    if(capabilities & 0x20000000000L) {
+        dbg_printf("This is cpu%u\n", cpu_get_id());
+    }
+*/
+
+/*
+    sysenter = cpu_timestamp();
+    asm volatile("int $0xCC");
+    sysexit = cpu_timestamp();
+
+    dbg_printf("Syscall took %llu cycles\n", sysexit - sysenter);
+*/
+
+/*
+    cpu_debug();
+*/
+/*
+       for(ptr = (void*)0x9fc00; ptr < (void*)0x9fffc; ptr++) {
+               if(*(u32_t*)ptr == 0x5f504d5f) {
+                       dbg_printf("MP Floating Pointer Structure @ 0x%08x\n", ptr);
+                       break;
+               } else if(*(u32_t*)ptr == 0x5f4d505f) {
+                       dbg_printf("MP Floating Pointer Structure @ 0x%08x LE\n", ptr);
+                       break;
+               }
+       }
+
+       if(ptr >= (void*)0x9fffc) {
+               for(ptr = (void*)0xf0000; ptr < (void*)0xffffc; ptr++) {
+                       if(*(u32_t*)ptr == 0x5f504d5f) {
+                               dbg_printf("MP Floating Pointer Structure @ 0x%08x\n", ptr);
+                               break;
+                       } else if(*(u32_t*)ptr == 0x5f4d505f) {
+                               dbg_printf("MP Floating Pointer Structure @ 0x%08x LE\n", ptr);
+                               break;
+                       }
+               }
+       }
+*/
+
+       dbg_printf("Switching pstate\n");
+       p = cpu_set_pstate(1);
+       dbg_printf("Entered P-state %u. (0x%x)\n", p & 0xffff, p);
+       dbg_printf("Initialisation complete. Nothing to do.\n");
+
+       struct task tsk;
+
+       _task_prepare(&tsk, (u32_t)_idle, (u32_t)&_stack + sizeof(_stack));
+
+       _task_switch(&tsk);
+
+    while(1) {
+        asm volatile("hlt");
+    }
+
+    return(0);
+}
diff --git a/kernel/core/main.o b/kernel/core/main.o
new file mode 100644 (file)
index 0000000..af67b10
Binary files /dev/null and b/kernel/core/main.o differ
diff --git a/kernel/include/arch.h b/kernel/include/arch.h
new file mode 100644 (file)
index 0000000..49ad39c
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the Corax operating system.
+ * Copyright (C) 2016 Matthias Kruk
+ *
+ * Corax is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Corax is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Corax.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ARCH_H
+#define __ARCH_H
+
+#include <corax/types.h>
+
+int     arch_init(void*);
+int     cpu_get_id(void);
+u64_t   cpu_get_capabilities(void);
+u64_t   cpu_timestamp(void);
+
+u32_t   cpu_set_pstate(int pstate);
+
+#endif /* __ARCH_H */
diff --git a/kernel/include/assembly.h b/kernel/include/assembly.h
new file mode 100644 (file)
index 0000000..37ff25d
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * This file is part of the Corax operating system.
+ * Copyright (C) 2016 Matthias Kruk
+ *
+ * Corax is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Corax is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Corax.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASSEMBLY_H
+#define __ASSEMBLY_H
+
+#ifdef __ASSEMBLY_SOURCE
+
+#define FUNC_PUBLIC(name)   .global name \
+                            LABEL(name)
+
+#define FUNC(name)          LABEL(name)
+#define LABEL(name)         name:
+
+#endif /* __ASSEMBLY_SOURCE */
+
+#endif /* __ASSEMBLY_H */
diff --git a/kernel/include/debug.h b/kernel/include/debug.h
new file mode 100644 (file)
index 0000000..af816c1
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the Corax operating system.
+ * Copyright (C) 2016 Matthias Kruk
+ *
+ * Corax is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Corax is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Corax.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DEBUG_H
+#define __DEBUG_H
+
+#include <corax/types.h>
+
+u64_t _u64div(u64_t, u64_t);
+u64_t _u64mod(u64_t, u64_t);
+i64_t _i64div(i64_t, i64_t);
+i64_t _i64mod(i64_t, i64_t);
+
+#define PANIC(msg)  dbg_panic(__func__, __FILE__, __LINE__, msg)
+
+void* memset(void *dst, int val, u32_t n);
+void* memcpy(void *dst, const void *src, u32_t n);
+
+int dbg_printf(const char*, ...);
+void dbg_panic(const char*, const char*, i32_t, const char*);
+
+#endif /* __DEBUG_H */
diff --git a/kernel/include/multiboot.h b/kernel/include/multiboot.h
new file mode 100644 (file)
index 0000000..7e2bd55
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * This file is part of the Corax operating system.
+ * Copyright (C) 2016 Matthias Kruk
+ *
+ * Corax is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Corax is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Corax.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MULTIBOOT_H
+#define __MULTIBOOT_H
+
+#include <corax/types.h>
+
+#define MEM_AVAILABLE   1
+#define MEM_RESERVED    2
+
+struct aout_symbol_table {
+    u32_t tabsize;
+    u32_t strsize;
+    u32_t addr;
+    u32_t reserved;
+};
+
+struct elf_shdrt {
+    u32_t num;
+    u32_t size;
+    u32_t addr;
+    u32_t shndx;
+};
+
+struct multiboot_info {
+    u32_t flags;
+    u32_t mem_lower;
+    u32_t mem_upper;
+    u32_t boot_device;
+    u32_t cmdline;
+    u32_t mods_count;
+    u32_t mods_addr;
+    union {
+        struct aout_symbol_table aout_sym;
+        struct elf_shdrt elf_sec;
+    } u;
+    u32_t mmap_length;
+    u32_t mmap_addr;
+};
+
+struct memory_map {
+    u32_t size;
+    u64_t addr;
+    u64_t len;
+    u32_t type;
+};
+
+#endif /* __MULTIBOOT_H */
diff --git a/kernel/linker.ld b/kernel/linker.ld
new file mode 100644 (file)
index 0000000..1a94f80
--- /dev/null
@@ -0,0 +1,20 @@
+ENTRY (loader)
+
+SECTIONS {
+    .text 0x100000 : {
+        *(.text)
+    }
+    .rodata ALIGN (0x1000) : {
+        *(.rodata)
+    }
+    .data ALIGN (0x1000) : {
+        *(.data)
+    }
+    .bss :{
+        sbss = .;
+        *(COMMON)
+        *(.bss)
+        ebss = .;
+    }
+    _mem_start = .;
+}