--- /dev/null
+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)
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+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)
--- /dev/null
+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)
--- /dev/null
+/*
+ * 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"
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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");
+ }
+}
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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"
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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"
+*/
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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));
+}
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+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)
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+ENTRY (loader)
+
+SECTIONS {
+ .text 0x100000 : {
+ *(.text)
+ }
+ .rodata ALIGN (0x1000) : {
+ *(.rodata)
+ }
+ .data ALIGN (0x1000) : {
+ *(.data)
+ }
+ .bss :{
+ sbss = .;
+ *(COMMON)
+ *(.bss)
+ ebss = .;
+ }
+ _mem_start = .;
+}