From: Matthias Kruk Date: Tue, 3 Sep 2019 07:05:17 +0000 (+0900) Subject: Initial commit, starting with the code base from github X-Git-Url: https://git.corax.cc/?a=commitdiff_plain;p=corax Initial commit, starting with the code base from github --- d0af1a7d6d38dcf9cfb2f17323645530cd0a0116 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 0000000..78dd5e0 Binary files /dev/null and b/kernel/arch/apic.o differ diff --git a/kernel/arch/arch.o b/kernel/arch/arch.o new file mode 100644 index 0000000..b02a94b Binary files /dev/null and b/kernel/arch/arch.o differ diff --git a/kernel/arch/boot.S b/kernel/arch/boot.S new file mode 100644 index 0000000..7e53bf1 --- /dev/null +++ b/kernel/arch/boot.S @@ -0,0 +1,46 @@ +/* + * This file is part of the Corax operating system. + * Copyright (C) 2016 Matthias Kruk + * + * Corax is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Corax is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Corax. If not, see . + */ + +#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 0000000..18094cc Binary files /dev/null and b/kernel/arch/boot.o differ diff --git a/kernel/arch/cpu.S b/kernel/arch/cpu.S new file mode 100644 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 0000000..b4a094a Binary files /dev/null and b/kernel/arch/cpu.o differ diff --git a/kernel/arch/cpu32.S b/kernel/arch/cpu32.S new file mode 100644 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 0000000..3562e2d Binary files /dev/null and b/kernel/arch/cpu32.o differ diff --git a/kernel/arch/debug.c b/kernel/arch/debug.c new file mode 100644 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 0000000..2e59868 Binary files /dev/null and b/kernel/arch/debug.o differ diff --git a/kernel/arch/defs.h b/kernel/arch/defs.h new file mode 100644 index 0000000..bf52790 --- /dev/null +++ b/kernel/arch/defs.h @@ -0,0 +1,198 @@ +/* + * This file is part of the Corax operating system. + * Copyright (C) 2016 Matthias Kruk + * + * Corax is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Corax is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Corax. If not, see . + */ + +#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 0000000..fb3c37a Binary files /dev/null and b/kernel/arch/entry.o differ diff --git a/kernel/arch/i8259.S b/kernel/arch/i8259.S new file mode 100644 index 0000000..dce961a --- /dev/null +++ b/kernel/arch/i8259.S @@ -0,0 +1,89 @@ +/* + * This file is part of the Corax operating system. + * Copyright (C) 2016 Matthias Kruk + * + * Corax is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Corax is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Corax. If not, see . + */ + +#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 0000000..02d25b6 Binary files /dev/null and b/kernel/arch/i8259.o differ diff --git a/kernel/arch/idle.S b/kernel/arch/idle.S new file mode 100644 index 0000000..9f5d073 --- /dev/null +++ b/kernel/arch/idle.S @@ -0,0 +1,23 @@ +/* + * This file is part of the Corax operating system. + * Copyright (C) 2016 Matthias Kruk + * + * Corax is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Corax is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Corax. If not, see . + */ + +#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 0000000..fa77260 Binary files /dev/null and b/kernel/arch/init.o differ diff --git a/kernel/arch/interrupt.c b/kernel/arch/interrupt.c new file mode 100644 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 0000000..c3b4f2b Binary files /dev/null and b/kernel/arch/interrupt.o differ diff --git a/kernel/arch/paging.c b/kernel/arch/paging.c new file mode 100644 index 0000000..e3c9712 --- /dev/null +++ b/kernel/arch/paging.c @@ -0,0 +1,277 @@ +/* + * This file is part of the Corax operating system. + * Copyright (C) 2016 Matthias Kruk + * + * Corax is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Corax is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Corax. If not, see . + */ + +#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 0000000..7e5594c Binary files /dev/null and b/kernel/arch/paging.o differ diff --git a/kernel/arch/task.S b/kernel/arch/task.S new file mode 100644 index 0000000..caf5d12 --- /dev/null +++ b/kernel/arch/task.S @@ -0,0 +1,77 @@ +/* + * This file is part of the Corax operating system. + * Copyright (C) 2016 Matthias Kruk + * + * Corax is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Corax is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Corax. If not, see . + */ + +#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 0000000..9e4cd05 Binary files /dev/null and b/kernel/arch/task.o differ diff --git a/kernel/core/Makefile b/kernel/core/Makefile new file mode 100644 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 0000000..3fb2790 Binary files /dev/null and b/kernel/core/core.o differ diff --git a/kernel/core/main.c b/kernel/core/main.c new file mode 100644 index 0000000..85e8641 --- /dev/null +++ b/kernel/core/main.c @@ -0,0 +1,178 @@ +/* + * This file is part of the Corax operating system. + * Copyright (C) 2016 Matthias Kruk + * + * Corax is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Corax is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Corax. If not, see . + */ + +#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 0000000..af67b10 Binary files /dev/null and b/kernel/core/main.o differ diff --git a/kernel/include/arch.h b/kernel/include/arch.h new file mode 100644 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 = .; +}