From d0af1a7d6d38dcf9cfb2f17323645530cd0a0116 Mon Sep 17 00:00:00 2001 From: Matthias Kruk Date: Tue, 3 Sep 2019 16:05:17 +0900 Subject: [PATCH 1/1] Initial commit, starting with the code base from github --- Makefile | 23 ++ config.h | 40 ++++ include/corax/types.h | 36 +++ kernel/Makefile | 22 ++ kernel/arch/Makefile | 23 ++ kernel/arch/apic.S | 188 +++++++++++++++ kernel/arch/apic.h | 106 +++++++++ kernel/arch/apic.o | Bin 0 -> 1332 bytes kernel/arch/arch.o | Bin 0 -> 18956 bytes kernel/arch/boot.S | 46 ++++ kernel/arch/boot.o | Bin 0 -> 632 bytes kernel/arch/cpu.S | 36 +++ kernel/arch/cpu.c | 83 +++++++ kernel/arch/cpu.h | 156 ++++++++++++ kernel/arch/cpu.o | Bin 0 -> 2348 bytes kernel/arch/cpu32.S | 67 ++++++ kernel/arch/cpu32.o | Bin 0 -> 616 bytes kernel/arch/debug.c | 474 +++++++++++++++++++++++++++++++++++++ kernel/arch/debug.o | Bin 0 -> 8496 bytes kernel/arch/defs.h | 198 ++++++++++++++++ kernel/arch/entry.S | 343 +++++++++++++++++++++++++++ kernel/arch/entry.o | Bin 0 -> 2372 bytes kernel/arch/i8259.S | 89 +++++++ kernel/arch/i8259.o | Bin 0 -> 796 bytes kernel/arch/idle.S | 23 ++ kernel/arch/init.S | 393 ++++++++++++++++++++++++++++++ kernel/arch/init.o | Bin 0 -> 3300 bytes kernel/arch/interrupt.c | 119 ++++++++++ kernel/arch/interrupt.o | Bin 0 -> 3204 bytes kernel/arch/paging.c | 277 ++++++++++++++++++++++ kernel/arch/paging.h | 61 +++++ kernel/arch/paging.o | Bin 0 -> 4064 bytes kernel/arch/task.S | 77 ++++++ kernel/arch/task.h | 44 ++++ kernel/arch/task.o | Bin 0 -> 764 bytes kernel/core/Makefile | 15 ++ kernel/core/core.o | Bin 0 -> 3196 bytes kernel/core/main.c | 178 ++++++++++++++ kernel/core/main.o | Bin 0 -> 3192 bytes kernel/include/arch.h | 31 +++ kernel/include/assembly.h | 32 +++ kernel/include/debug.h | 37 +++ kernel/include/multiboot.h | 64 +++++ kernel/linker.ld | 20 ++ 44 files changed, 3301 insertions(+) create mode 100644 Makefile create mode 100644 config.h create mode 100644 include/corax/types.h create mode 100644 kernel/Makefile create mode 100644 kernel/arch/Makefile create mode 100644 kernel/arch/apic.S create mode 100644 kernel/arch/apic.h create mode 100644 kernel/arch/apic.o create mode 100644 kernel/arch/arch.o create mode 100644 kernel/arch/boot.S create mode 100644 kernel/arch/boot.o create mode 100644 kernel/arch/cpu.S create mode 100644 kernel/arch/cpu.c create mode 100644 kernel/arch/cpu.h create mode 100644 kernel/arch/cpu.o create mode 100644 kernel/arch/cpu32.S create mode 100644 kernel/arch/cpu32.o create mode 100644 kernel/arch/debug.c create mode 100644 kernel/arch/debug.o create mode 100644 kernel/arch/defs.h create mode 100644 kernel/arch/entry.S create mode 100644 kernel/arch/entry.o create mode 100644 kernel/arch/i8259.S create mode 100644 kernel/arch/i8259.o create mode 100644 kernel/arch/idle.S create mode 100644 kernel/arch/init.S create mode 100644 kernel/arch/init.o create mode 100644 kernel/arch/interrupt.c create mode 100644 kernel/arch/interrupt.o create mode 100644 kernel/arch/paging.c create mode 100644 kernel/arch/paging.h create mode 100644 kernel/arch/paging.o create mode 100644 kernel/arch/task.S create mode 100644 kernel/arch/task.h create mode 100644 kernel/arch/task.o create mode 100644 kernel/core/Makefile create mode 100644 kernel/core/core.o create mode 100644 kernel/core/main.c create mode 100644 kernel/core/main.o create mode 100644 kernel/include/arch.h create mode 100644 kernel/include/assembly.h create mode 100644 kernel/include/debug.h create mode 100644 kernel/include/multiboot.h create mode 100644 kernel/linker.ld diff --git a/Makefile b/Makefile new file mode 100644 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 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 . + */ + +#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 index 0000000..7e5f445 --- /dev/null +++ b/include/corax/types.h @@ -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 . + */ + +#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 index 0000000..a5c7548 --- /dev/null +++ b/kernel/Makefile @@ -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 index 0000000..67a8275 --- /dev/null +++ b/kernel/arch/Makefile @@ -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 index 0000000..986199b --- /dev/null +++ b/kernel/arch/apic.S @@ -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 . + */ + +#include +#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 index 0000000..98a4e38 --- /dev/null +++ b/kernel/arch/apic.h @@ -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 . + */ + +#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 index 0000000000000000000000000000000000000000..78dd5e0cbc240101035e2c3f88f8e65a0d924f12 GIT binary patch literal 1332 zcmaJ>O=uHA6n>j*G{#mV_8^KHY+?&)Op1b3ZBuQ9N^>VBxuYlw zNmIy6e-Y6Suba8zxNh>(K`L+im(*~jqkjEvt%xPaKh{q0=-xv%BY0B|!oB{UxU9ZwBA}sIJ0^fE9 zd|3_qUBXxQ)*FXe>MJ4IM*GVNz;+@JRYRaQe0e;%-O3I+iBO~2to66^TUVKguf{*e zH_N|HJndQh_~}b&Ex34^XthxZ;t`>rjb<%DA8y<#_)t?JH(BN6z_-m>e(PLK+3GB> zcdQL(4ckc08Qjg254+zv{!)Zp`o!|5TMcV$w=WM zbj61wQWCnuMW@Ne6DiiA@Y2Pvj_N!@eK{3;#D@ou`NP`3;n@1-7iJ~7w4lt6G^ zAYS1fV&+`)(jx?y1q!0Rfw-#$TOwwMlc(qV@aui}%|1+;k+n5FYnuyNGH;}G(`==z ze8Dtw1&g%VjO_^iM%oh{TFGmso)$7A$CWhGCT9j#Fl4CbjMnn0Tqcvt(#&*P%bRFq zmb6s9K$@keGw4a1(XEteUU&~K&s~9e-x!ZGK0=gbkL&n?`J==a z-obALKFJ>6MW^r-wH7jVavI(?UH@1{ram9F^`cGDnWUYh=(N?k>nQLaJBu9u3l0bk z{{y<15GKP@z=tprf}h7#dw|%7!5S5Vzut(z@+M9qIR#Fdtakwf>!t3!ObDTb?6IA@ ow!#Dk_Zz_Ab@^U#Z?YCbTEV1u90-&3jsdso)&XKt1TS@e0JsYFMF0Q* literal 0 HcmV?d00001 diff --git a/kernel/arch/arch.o b/kernel/arch/arch.o new file mode 100644 index 0000000000000000000000000000000000000000..b02a94bff5f2b95a3d2cdddb5c1f000f1b9cff57 GIT binary patch literal 18956 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 gOx+M=yPf#sadKo4%=*YivRvB+oNdia. + */ + +#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 index 0000000000000000000000000000000000000000..18094ccd7b8edbf0a79aab92052f200f506575bf GIT binary patch literal 632 zcma)3u}T9$5Pf?W%?TnA8zG>Lf*>3g7M3tQ?G%|9~#LpP5PPb zWjO|;ijwa24Z5S;j_F-vm}Q_%4w_uz;&$k4N_P32`c2>rW#Zi@depZMi374qIa iL;984Qdjzr-t;Y|cx7x!;-PidsTX|_4-V8sR^J!+9Wl@V literal 0 HcmV?d00001 diff --git a/kernel/arch/cpu.S b/kernel/arch/cpu.S new file mode 100644 index 0000000..9b48793 --- /dev/null +++ b/kernel/arch/cpu.S @@ -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 . + */ + +.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 index 0000000..7164830 --- /dev/null +++ b/kernel/arch/cpu.c @@ -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 . + */ + +#include +#include +#include +#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 index 0000000..0cd8c66 --- /dev/null +++ b/kernel/arch/cpu.h @@ -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 . + */ + +#ifndef __CPU_H +#define __CPU_H + +#include +#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 index 0000000000000000000000000000000000000000..b4a094a458345773907b29eb98d1aaff0a4e82ef GIT binary patch literal 2348 zcma)7T}&KR6h5;%)TLl|A!}@Gqa!Iz4R*5IBGRTLKpDUUEw=Eab-F*pk1fl(JEMzf zqp-!W8CQuunD}6#Pd@nIgHfX|P})>|@$c1`+Gt`64{G+Y$@-l;b74wo^uV3-_uX^u z{pQ};*Nl-tMNvqKLSfqSh%WE)GMz#lq85sYd;~t@8ZpKzf1D|AsDIw6*X#3FLWsCV z#C^KCGOW5ra}T{u6utZz!oqx|t%u&^$VVdb7Mt%0bCJl--}*|}@2rsB+C%R{HT6*C zb&4*2h=gmzqhGAJhd)Zq)FkTOZ)z8nuQPg4Osnj=5!iDnC?=zg+zH zs*5X5lr4g>t9+?O&V-j}$M!(;9wO(c7vUB1ZUE->qs9i_Ro&UBJGE;0AnK0FrLDIy z44dN?r$+@Kc^5!gE*mvv{!*=uaP*CFyl`(j^i=NU)P?D+Re3_aKGob5@J+Dn=+haP1o(Oo*u4-GZR^b43<1rV~yjUQNZ_a9iJp_3<% zYljA`^mHnxb?Ha-#NlLjN7hOobCQpF0qsa4`DEgWWEbkixhO<=^)x9LBg(#JRb9ft z)ezgy2}mb=>e~}p4E5jNFi;MMA6Kre0jD9{i^2Ktp@W#vbpgR`Aj)zMqIyciO1>>) zzPqWor4*I^WVFf{~SWc^F&N5ga<{)qUb?Zr@p=O>}U#J6=z!s6Bj{iZDk zR+yT%`MbCI!PPT9L=OO=Vcf<7TIiqpL;eirt`&$QzR#*P6cKBcA?EM}=|HnTg&}$8 z`Gr8fHPlE;0iW^y0W-}BCzmlzJ(=iEl8IAy&l6>urS2|$(z4Bb#H8Y$hw!x+@HKN6 z!hyKRnqR$MoSU&zX=uCP=_zRytP8qrm2A?pDLX}ax>zK=FzY#-(0AA;coLI#%7Ftt zGdsf{0n&4`wxtg}Gk&;er!wbJ7~QNXbE1%%u}GgR%sP22@Ba$_N`RJ4>4e4GV}AJz z@Ll7v9d`mTiR15q#61EV6mH%o<}b{jVqZANvJZoQ=Xx<%p2xdjj=3-2RIbPM+c9{K zyuCw#S_q3A>kbUY{}(O+4A+xohGCq8FNOQEbYqBp_`r{$WsdW5A7k5apWFk-?}X=Y zf0j>y(>+r>Imctp*CL3=uYP~&%f3|~C(}1zEJ+ZwTx$h(kmsx5SwoC@<}Z@und{10 sFlh=zoFDe39$pGZn=Bj=uaWEJfn}1^Nw)0RR91 literal 0 HcmV?d00001 diff --git a/kernel/arch/cpu32.S b/kernel/arch/cpu32.S new file mode 100644 index 0000000..211f3d1 --- /dev/null +++ b/kernel/arch/cpu32.S @@ -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 . + */ + +#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 index 0000000000000000000000000000000000000000..3562e2dbdad174d356484f394968fd86ccd8e9f6 GIT binary patch literal 616 zcmb<-^>JflWMqH=Mh0dE1do9s0Ln1|E6`wIXJBL4r@-*wUpL#q7ZQhefTZ~sb)GoP zzwQOU;o;z&Gl3%fM%^(g9BG|5_zj{D!%W6bquRy*w4Dh>Av2nL1c0vN0jl7Jssiy9 zfoxGEzCMsGjl^e2E+~ypPc4bhOo20#6AKcPGIKIZGE|$m*1U5;`zNKpLhF0JBX$IRF3v literal 0 HcmV?d00001 diff --git a/kernel/arch/debug.c b/kernel/arch/debug.c new file mode 100644 index 0000000..0467265 --- /dev/null +++ b/kernel/arch/debug.c @@ -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 . + */ + +#include +#include + +#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 index 0000000000000000000000000000000000000000..2e598687b93165ec61bdefb29519937443965d27 GIT binary patch literal 8496 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. + */ + +#ifndef __DEFS_H +#define __DEFS_H + +#include + +#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 index 0000000..0603c6d --- /dev/null +++ b/kernel/arch/entry.S @@ -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 . + */ + +#include +#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 index 0000000000000000000000000000000000000000..fb3c37a79d6a5745e2051d4ee220018115023154 GIT binary patch literal 2372 zcmai$U5HF!7{}k)uNka07Ue6VC2Y1mV=T(|*tI@)eJg3qGHY#SRx^hzE6K+dYzYK zOD&vbnEr|LcMjLzB#qEoQlHkIeoPH$!6bYJK-PVw(C_-ZO#-O@pe zOI2C^dY{6Dup^+VJVXv-b|Uhy!ZGog;A-*+coO+ia1Hrd@Lclk;0E$G@G|l=xS9MI zxP|;2cqjQKaGd-)xSjkqI7R*d?2ZOZ-l=g-vob0z8n6L`~X}Y9T{@H4#WGc=3TC}dn|X8>Ysh$F=Fh@-^w zi5rL)5HBQNMC=SI%#|H3?Qm^}i#uH1;qngGcenwEJBXkI*%NOYd`2@qqZgmiiqGi8 zXEfq7`tTWT_>3-mMiV~EHWY;`%Qh5exVCIVafYkQHWX*LzHCErhC3Lv4H51j!W~4= zLAE<ktyzdV+@1y-sH_i#y6sUwo-D|JG$e6iMLyHjqW z4cX1u+~H9sd9cn+9(7gSzJ!}lb#2+KckBN*PsIv(Y$^&XQCeM;1BKzC{1(XX#qz@O zM?pOQ;BvfVO&MPDZ^ev)d%s9ey%XTL3{Pvpvi^VTWIa8qst*Sa;Z4%7)RwyPd`oZM bxqvE)$#e8ZukPp}>)zsX)XN(R!&~. + */ + +#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 index 0000000000000000000000000000000000000000..02d25b687e61ad74df597e25519039ac58ef6051 GIT binary patch literal 796 zcmb<-^>JflWMqH=Mh0dE1doB?4wPd8R-nPa!NAUt0b;-S^Z);U!vkqM{{HV|Q33Os zkFfkcYBJX;9nH2-j@5pVwCUoX`B!()R&4b!s)&lGlm zOnc3`18Cg;!=8DWC7FpinZ=oT=?a+^My8eu0iMoWASJi~s*4$bK43;s%*?=o;wO*_ z9wZe4Kv@YCJ_Ca?kgow11IZf!*|JD{M=V z=IE8AR+KR4r6iUlGUz207eie~n34x70Yx*&J`e!Kbu^d-Az;h&g~*70QRjLO+m?9KJB~w4v%@>Xrlf$N;7eL<55Z4psnJ3xF8pUXa}& ndj)_P. + */ + +#include "defs.h" + +_idle: + hlt + jmp _idle diff --git a/kernel/arch/init.S b/kernel/arch/init.S new file mode 100644 index 0000000..33ef2bf --- /dev/null +++ b/kernel/arch/init.S @@ -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 . + */ + +#include +#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 index 0000000000000000000000000000000000000000..fa772600260386468f9e41ed3aeb6036cb9a137b GIT binary patch literal 3300 zcmds(-D@0G7{;GTChbO}o7z@Wt(wMdt+q+K+ooR>2_$NeqP-|usIWhDy*PSfxm+y$I+<1cltFtEootM!b;RhzrF~Oz}cckxJw9%+Ac7oD2T|5A6Ql zXU;kA*Us#mvyUHo!f_l#!$Cc23OI9nb!K;ft!P97{*9JdNx$rVAO@lV&A_}Q=DS?M zFDK@EQoPD5J*lQ;4l)sH7w?ua;ij(tQ@!ruLK(iBN<OrQ zE+)pq1jbu{2?kKGAw~)I4b3)V=*vp|kY9F&7_OEpm)0enbt$cwT$n6RRwl1ce*fz= z?o424b{mpdm|0%jw0L=D&0_1~)J)gnrkP$Um#iZl&85r1_n%*=taJ0@YJ!UH3z$%~ zL6(!u?O@8k)&A0E|JM4k)#u#QQTF+~`>8fEm!=?HHNgMIS^7~$Xol;i>Z4lb-ISB4 zR-i!D3O1(vt1ai*iNjS7SKWy@zfyUn?CnUlE%?{!{hRO_ldTp1+ty@TB`}%;qkIPg zj3?X5fyE&ZaUU$yiFOTTC74=o)$ zRbkDl?`v!R2TT8K=^K{*+tRD}utr1v*IK&O((RT$VCg3^+9P z*Rb~)_I|@ouLx{LPMe|AX6&>XJZ(l#o8i-D{Ir=s+RPxs4DzF1+=kd@GO^8EVw(xA1r)J`B7p zGWplUM}XJGM}ap)zMS6@S=2?b9k?WR08`=);EKp%r^Phzk(dEy#9jRAD4ibh`j3-d zvC0#XRm`32@N%a-bjaeLSwA|Cm&`Xd_y5OW`N8>PRk&t1d5gbqG$NC2>q(6a@2^j)X7C;PV;fiatI(hBKl#(%$RFDi_>KH6(w{jZf1){c ponnTYczXsu<*%6^)e!ljiHi(4ZETGE=~*+^_3}PeZ=w;c`xobo5zGJp literal 0 HcmV?d00001 diff --git a/kernel/arch/interrupt.c b/kernel/arch/interrupt.c new file mode 100644 index 0000000..49d3768 --- /dev/null +++ b/kernel/arch/interrupt.c @@ -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 . + */ + +#include +#include +#include +#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 index 0000000000000000000000000000000000000000..c3b4f2b0c9cbac59998cd2eac598c4035fd80e3d GIT binary patch literal 3204 zcma)8Uuaup6hBGRt?jxx+o{u4z1S8r+g;LGx4M5eZPQw4wlrzSWR~kqa@%BUlW=px zG8Npo6IZgp@JU6nf)9cN|2)mNL8qcmdr;Veh%d^pMGyw=VOW3X%XgF8Y*W8-?(aM2 z{JwL(Kj-_JH$szR9*>8d=Aj0vX+#&BE1m%Xe(Ioh;ctP?ye*KKrC($An(yYF_4W00 zD_&Sip+5WeVQaH}`vvQ<)!tGlV6Qbr%Jvj|5y7*sZCmZI*ILWA;kI28BZGw#!ga>& zD%sHJ+p|}-06L|E|z4e+Ovw36WyRdYDnn>Mca8&PrHYtLhbzYWB`| zE0tAlcds%W5V5wOZUvUkiwUhZR));Qd+yX0~3qRkr_flgf4n_B?X(WZ8b2J7s&C!P(IIxmHf3k&me~+g%EGmS+61 zsc8Aq08G)PmAl6gb&ZA~!*nD(L0!WU>N+|Gj8fOkD0LkP!v{SKnT|n+KL#8JM#d-_ ziXEe_;0Oqi;~*akQ7|$wqJ&H{YwlM9#h$=mv4vu}f|<@1@=7{m8KzmtSuGSb;@PZ~ z&djT-+CmeKL+L3f*+imXnnsdqE>uhyIV+vbu;WBeezxjWD_N98HfhLA2sEY_7A)iu zmOaJ&Jb?pBXlyb#9#algXB5%r4P{Pn^<>gC^7-0qXEG^0lUy*8is2-u>crIqk(S7s zdQnU03k!ZMvDn99<#*SC7Sb?ItHi(x?ruJqnjozZF4pak9gt3l0_leMA$^blgzw@Y za%KKcmH5-(uhA_=-*W_D0>3^ z`vTAP@5MOI%gys@lsvCDd3Lt?d>2qE3T!+VZoly-*w*x>cX(^#sNLZG`Rf(X1ZPP4 zFV}NEu5ps^y^WYWe|MZ*g(B8}fqiJaFWh)f-WR=^O{!Hu$ZGS^pX*fxod*25TLU$^ zRd_em>6`2HCfX`3(?AbS>k%MdK0Y%K)$_ShYpp@Nl5X9JR%;vvqo^PG79kPebR}e3l$vyls-h@yZbA9NGV_^f9!1 zv3~ar5f>n%FB+t2bA?Po)71XJV1P7`oQt7p#lgMmykTj%gl44*nNw=KNZR=1(c$2v zc64kk7Mj+kgTs>{jgs+sEoWlz9PVDOK$@OQCp06Q-f-0fOV6Yeq~*`#|0R!JtlU5E zgCtI(rJd**tfLua!uQSBL3CK^qf&oK>YCJfKYMY35K17|FzfF~yb9!a-vBw@kBkoy z{Q=~>w}70t88y|6a_nRT|0y8z_euSb)L)i*T+ZBo368#eUB=SBoZ$RRpM1I5AJ|vO% zm-QDVPD+eORDfRm#9$s{O5#OE{8m|Jb#jP);PP|?ing3tB0609x39}8ISDYZQ zb6#$umVi#Yv*=6^u9?3f^VdoaPMs00#GZKgS~du. + */ + +#include +#include +#include +#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 index 0000000..a44080e --- /dev/null +++ b/kernel/arch/paging.h @@ -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 . + */ + +#ifndef __PAGING_H +#define __PAGING_H + +#include +#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 index 0000000000000000000000000000000000000000..7e5594ce157ae24814ca7b5c6ceaf19a7f2e394f GIT binary patch literal 4064 zcma)8e{7Uz9e>`t>*%jhS^+Ve^k&9n0%r>?f}2^(`ob{nI0vU>vwOW>U)n-@t#@xN zEJG-7TX=kS+QiMo=n^y}E^&#tkYy^%dTm)N)T|7Q-9l#38rxp~aIwjVAv-_c=Y8J0 zTcOV9@;u+4&-d5!e4qDD==HlbO=IrRn3rWK#%7BhNtFZ}*=Japlox^~y&}vI|A)P> zZuWLMoz5fPn7)XWiIcSU4|SK>3;BorhyAmpY>%$u`l8Sm|2Tqu`|X9*cWkte7c*CM2&Bq| zJ|lvwL`|`#PnCvl5DDcOZPFg{L7nymE9CCY+Ast=hkGXM<2P8(y0HNtnZOYGlnCA6 z`gtC@kWzf7qUT9GreAQVR~+h90?wY2S0_u8^QAn=ukmp{K&K|;nw<7f`F+9J#K-A0 zRevB~3dyHE?X_=d)Y+?*Ym@V91teFB8Ye`nqC9by+SIMcrARolm z^V_*U0h4~uF7Z2^>vwLSR8wVHpPXOs+z=$h^+7&mPcyE+C_*qYm{>h5JmM)IAG1GV z{LNNmkMI{6?{B9tE^&B9IebCr7wvKF_oyZl zjb}x}8ScBn4_xu3s+Ze(Qf=*%v7U5ewg07YJ?n2xa(<1I;D$63=lw@1TA5}4^Ax^5 zA)WHEqT@sS%`TEo7U`qB-y&(~qL4d8f+XT)V)Ei){_SC(JR|@AKBL%Ubb<14KHsah zkB_pFfm7&|)WeB^2oepp{toMMZIbd0rnEsi%1?PTN>0ClI*;j-RJ>HJaJo4(iRMrK z&7)0V*k(gY&Klwo{*sy+#*G zK6sgHFZv{nlSXUzV0&(B%ibu`uP4mKXPz}0M<8xDTf&iJ{=KzZwr%xybT*qTSgSjT zgtSHW^*BPB!LKfqO-@}+}7;h>u-TZ zs~IyNV|p~))J_{W#FYtrpt@R&wrHD$s2ILljNOO%MNHv)a70u+IKuWk{`gn@8|%!b zws6$HJ+LiMv88gyre?EgXLsep4#U5-qVg*h)s@?^Z#5j-^d{i+F>-03nc-zCGB_b#?4+*=4a!9WT?^>e%>#`F(Da2N zAKD%J-RL01@XCKD4(`zRW(g@@xrC-jv*VNhgvg$UJ)^`FQyDmIS#?(CDP$*dXv*QG zCG^=P^shj>XHNEhlOr$l6iJ!OB75(+1R&AbwlI#Ev8dT@L}J^RfvbP0J=_v!#-Uia z!!$a=UCf9|9K5&{BMsS}Mpx^xxDjq|?~E|RIMf}D7)GG7a@$U7pXRn0?3rQ9gzV^! z?E!S0(G@YQ*6!$$K=>##_SEm&RallkGcuK(^ zC`e~O@?R?WI-n26-UamFQJ4ZG`yVLzKNZ}CW+8u1EBIptf2!bl1z%V2V}b>U+vC8M z3a$n8;ej|vH0*s>!4DMt0@{rB1r)4S@N0my@B2h!-;Wf03y|`8N6~*)@UH~X0&@gm z??XV}=NbEtk|Qmqfe%v>${qqu^(DR^(1Vz26l_-TMS^IRR|uA13B-?eSm7o>E9Ssf z7mJzg0n0pUu|RX!3bQ~{JkA2KPKO{NVF5yL;lk}qDhKXzEpWM(mEp<+BAp!_W)yz# zsW1b3o(yflg^L`4GuSp;oqNv$EwRq-E`xiT*jxF$f{~rB|73k^K#rw8wp^8**%cov}yn zF6p~^LFmc%f|M}G9*qi2vWH`rgY@XU-Qns{ez|^Uma(@3dbxQl6fx!pk9<=+ZXWf( z$=*H6@gnTGzQC3;f~^X7^=>Vr*QfL-9~!rz7jRIyk}sO{{Uzv*FMaY8l#%@c3Z&=O zWi#|HxSIgoSYHO7n{P3iX(M=)FMVCyd~. + */ + +#define __ASSEMBLY_SOURCE + +#include +#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 index 0000000..0cd1fd2 --- /dev/null +++ b/kernel/arch/task.h @@ -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 . + */ + +#ifndef __TASK_H +#define __TASK_H + +#include + +/* 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 index 0000000000000000000000000000000000000000..9e4cd055ad209bd5acbfb90e0ca2a37f77b6114e GIT binary patch literal 764 zcma)4F-yZx5WbkywxG0bf`UOK7L_1a!ETXSQS2bCg;Ir>)Ac_zPV1 zKPZAYWK`&;AWnk+z)8G|d72hPKe&GP<-U9GlIw9Uza&W#2uL8qj{>+3MA|o`AO=w= z@0AXyrIL}ul$^tU(s*oojtcES||P!^`7WgbWRNT26Bg22BqVjlBjTKmsvVL}$ZPn4)lRsaA1 literal 0 HcmV?d00001 diff --git a/kernel/core/Makefile b/kernel/core/Makefile new file mode 100644 index 0000000..92db6f9 --- /dev/null +++ b/kernel/core/Makefile @@ -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 index 0000000000000000000000000000000000000000..3fb2790a0c198c88586878f81d8b1f604435f679 GIT binary patch literal 3196 zcma)7Uu;ul6hHkl=qAuHh=4%2F)SG}t}O%HCMc!r7IcHM4TxE0bJyLib^Vw2HgrTZ zaGA0+O%@Xqq9zhGkq2UYP%!EPWFi`Q&<7I}P1uVB!V;D20S%=7&e!jFo+ksU%cQ3I_M@fu*xTY`3Y^7mW!%jI$nJLc{@ z06u!8&z#*LyeFrfa2G?KVm&%@*4-N}neb3pgw1b+`?9-8lcAX+ezYeX>Ng#Dec-NOD+ z*bZS|HfKFYj~wDPwu04KqauhmiGH0qyR2kR*rN3#*FrZPG{q}2Z#j5{Bj$;l$SUfeVWO9aP=yeoI8G06J z;cdd9H0D*M2|HKVA||~*6*uBqBA(NXIGCbfP3VTMDhJY-5_pWXGMrXL?rOO@$MIfr zyy|hRU*>k7!2$ED+aP1OlSF|Po(bo^0dc$qjxVjzFfo}uX z0#`wXFmuJw;>f)V{V>1FbTJ1%Q5Mc+Vc%I{&HJb;h@)-l(1+q$O4+5hsJ?Cf)~&<( zP+Q)=rQ+aCe8#uaze|o?Of9T}gsR9@Y+hXO*u_P>>UnXA%4o++=K(Ai$-*kVE_$pg zzN`u_ufi)9)M+>URrVl*>t01%#0*z0h%c^${eulZ4*Mq?UJv^zJ}V(EQl!O-_xtH8 zyr&Ak0BoIK1HKow#T%S8G$Ju`aXbOdHs24%<1)^Q{nnW?Zg4K4ci51^@lP!P&G<_+ z1&uGsO1fL7q!v%9QBu2G(fmH{{M>Elu7#qRd?cqEk;;>yh@s`iBAKk7(XzTkIq|MY zJW7g03az`;Q63SE7_oe6Ow|e$i4P}`p2@~jMkJXrh7vS9G+MzUj~X+CFl`Vn)py|JZWe{&_=eRW0sZG6RM#X z3=+Ni=xeZO49Bf9LpD9E8Cu2GW08@pmefhD_=a*hQc;7G_*WryG@H(6NKK_tkGl>W z<^o>144CHsks^}#ty{7K2G<5`5AmDFvPG-T<2|zS_?}sLn_%PE9#*st*aJ8ROE|{D z^@H!}UNn|-D0yoU. + */ + +#include +#include +#include +#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 \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 index 0000000000000000000000000000000000000000..af67b1025d4e16f2bf72686cc95163af64e95b53 GIT binary patch literal 3192 zcma)8Uu;uV82|cb&{d#gpnyQQ8Wx9aH!TC)CMu=t7UBkF8=zV6=B~S2>$2oL%InTSRo^udHg6ZRs3utX($z(i7i-?{g8cMV3*cFygQY_LJ(_t2R zUnCZo{7ZzG4P4#r9i58aVOK-oYV=NjtWuaQ8*826jHs{W-dAFRFK~sk_ewWXLFxbjfwON9Q1(CdW$tC+|>T zvIE;XJzdu3hu%<*%wS^&PR*@uAad-ii1wK?ny~z^*y1f4^K2;_k4#aI!?Lq$z>G@4 zXP<|dzp2LmrptCuMdwS=`M^~y)mtgdBV?$CTQ*`&OGzAed78XL=Fyu~Fgf>orQ*z? zyx4+LqP|$C6f8Cc+l$hWDUWc;Q4D2ads?Jar__`vv^Xe3d-n|Gk15TOEz-7Ns9ow)bv=<(^U|xi!nm|+0&sVnC(H5p%YF*&=-l4c8SJ2N zVN42j@SF~cWG1r76cWg!rKY^3>KOera5SmM6Up?Ll+Ej^uK6jN*0mgHu~uP_nhLVi zjGZfP5lQb&C-tP7O6FBPiAZroO=-F&OZzfN332p{G?J11RPt_~DQ(z1Lp>4fTXUB- zoK(}&PPt7Ewuaibj%dRjh0qq$z!|;}+!5MIwA$Jc*YSRGo$$HVFY|iOq8RvwZm@i) zU!w2|-=urb@;az3=zLk&{yMl-U-uc$yI!Nt)9acEe-pkLzJXwHbF2h<65I!nReq1* z;TU|KxiOa;+s+AX!Dhj#;LqC4OMg~uouvmq&gLP`dZBq}$pV1pp`|t0dPFU&N4%N~ z6b~(10MIx%2U75)0!>Pwj94^wx@R-ROC2^}s&BYT+5;u?H z*@BYi?}*Duimv9z!PT;A4rvIK7gw5>!}aUNh2rY*KS}g7<2B~FFm3~`M=5qddT}ZE zuN&jD7Un%+yas2$aw8=3c3AjD3+s>^_c$cSH7x&><$vG8=PmrHg+I6C7nc0e@_)w? z$^LBFf3fU$S)wpq_=kY=SqjPdtg`Sr3qK3FwUJ0>`zoSW*pA2J0LzW$U9QJ#c7fN2 zQohI%SLkDw%ke)8%N6E6xiM!KFw2xBd4JrvvOM3-S5?j*o6yx^NIhrDgstVYl&ot- zo#YW!S4keu=SgN`E@K+lDL=k|#Kgz>P$M#4-U<9IAvvAF^V_rUAivkBND*91D5E)b zLL+%BmnmeC;{R>uLFBi=Zrh>oTM|G=DT$imx~k>z9@#vULY21(I*zUS!gWC(!d}{q zecbrH;X2)o&g}yBbuFCyU4DJ|n;gFho#)su(ua;%Fbf~ct?11EFCMRt`EhK=*%60q~*ecU#Oxb}Xp$5CLXk!rCYc^*IBU|$Kl4c=j3@Y@gw0e2b=c~6J}Ji literal 0 HcmV?d00001 diff --git a/kernel/include/arch.h b/kernel/include/arch.h new file mode 100644 index 0000000..49ad39c --- /dev/null +++ b/kernel/include/arch.h @@ -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 . + */ + +#ifndef __ARCH_H +#define __ARCH_H + +#include + +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 index 0000000..37ff25d --- /dev/null +++ b/kernel/include/assembly.h @@ -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 . + */ + +#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 index 0000000..af816c1 --- /dev/null +++ b/kernel/include/debug.h @@ -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 . + */ + +#ifndef __DEBUG_H +#define __DEBUG_H + +#include + +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 index 0000000..7e2bd55 --- /dev/null +++ b/kernel/include/multiboot.h @@ -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 . + */ + +#ifndef __MULTIBOOT_H +#define __MULTIBOOT_H + +#include + +#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 index 0000000..1a94f80 --- /dev/null +++ b/kernel/linker.ld @@ -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 = .; +} -- 2.47.3