diff --git a/Makefile b/Makefile index 59ac6f0..a0bec79 100644 --- a/Makefile +++ b/Makefile @@ -1,90 +1,26 @@ -# environment +include Makevars.mk -AARCH64_TOOLCHAIN ?= aarch64-linux-gnu - - -# Shortcuts - -CC=clang --target=aarch64-none-elf -mcpu=cortex-a57 -LD=ld.lld -OBJCOPY=$(AARCH64_TOOLCHAIN)-objcopy --target elf64-littleaarch64 - -CFLAGS += -O0 -CFLAGS += -g -#CFLAGS += -nostdlib -#CFLAGS += -march=armv8-a -#CFLAGS += -std=c99 -#CFLAGS += -pedantic -#CFLAGS += -Wall -#CFLAGS += -Wmissing-prototypes -#CFLAGS += -Wstrict-prototypes -#CFLAGS += -Wold-style-definition - -BUILD_DIR=build - - -# Files - -KERNEL_MEMMAP = aarch64/memmap - -KERNEL_SOURCES = \ - aarch64/boot.s \ - sys/main.c \ - sys/uart.c \ - -KERNEL_LIST := $(wildcard $(KERNEL_SOURCES)) -KERNEL_OBJS := $(addsuffix .o, $(addprefix $(BUILD_DIR)/, ${KERNEL_LIST})) +# Rules all: kernel +$(BUILD_DIR)kernel: + mkdir -p $@ -# compilation - -kernel: $(BUILD_DIR)/kernel.elf # $(BUILD_DIR)/kernel.sym - -$(BUILD_DIR)/kernel.elf: $(KERNEL_OBJS) - $(info linking target: $@) - $(LD) -T$(KERNEL_MEMMAP) -nostdlib $^ -o $@ - $(info done: $@) - -$(BUILD_DIR)/kernel.bin: $(BUILD_DIR)/kernel.elf - $(OBJCOPY) -O binary $< $@ - -$(BUILD_DIR)/kernel.sym: $(BUILD_DIR)/kernel.elf - $(OBJCOPY) --only-keep-debug $< $@ - $(OBJCOPY) --strip-debug $@ - -$(BUILD_DIR)/%.o: % - $(info compiling file: $<) - @mkdir -p $(dir ./$(BUILD_DIR)/$<) - $(CC) $(CFLAGS) -c $< -o $@ - - -.PHONY: clean run - -# helpers -QEMU_CMD = \ - qemu-system-aarch64 \ - -M virt \ - -cpu cortex-a57 \ - -nographic \ - -smp 4 \ - -m 4096 \ - -kernel build/kernel.elf \ - -serial stdio \ - -monitor none \ +.PHONY: clean run debug kernel +kernel: $(BUILD_DIR)kernel + cd kernel && BUILD_DIR=../$(BUILD_DIR)kernel/ make clean: - rm -Rf ./$(BUILD_DIR)/* + rm -Rf ./$(BUILD_DIR)* run: kernel - $(QEMU_CMD) - + $(AARCH64_QEMU) debug: kernel - $(QEMU_CMD) -S -gdb tcp::1234 & \ - gdb-multiarch -q \ - -ex 'file build/kernel.elf' \ - -ex 'target remote localhost:1234' + $(AARCH64_QEMU) -S -gdb tcp::1234 & \ + gdb-multiarch -q \ + -ex 'file $(BUILD_DIR)kernel/kernel.elf' \ + -ex 'target remote localhost:1234' kill %1 diff --git a/Makevars.mk b/Makevars.mk new file mode 100644 index 0000000..44e226e --- /dev/null +++ b/Makevars.mk @@ -0,0 +1,32 @@ +# +# build.mk +# Ilja Kartašov, 2019-11-29 17:38 +# + +BUILD_DIR ?= build/ + +AARCH64_TOOLCHAIN ?= aarch64-linux-gnu +AARCH64_CC = clang --target=aarch64-none-elf -mcpu=cortex-a57 +AARCH64_LD = ld.lld +AARCH64_OBJCOPY = $(AARCH64_TOOLCHAIN)-objcopy --target elf64-littleaarch64 + +AARCH64_QEMU = \ + qemu-system-aarch64 \ + -M virt \ + -cpu cortex-a53 \ + -nographic \ + -smp 4 \ + -m 4096 \ + -kernel build/kernel/kernel.elf \ + -serial stdio \ + -monitor none \ + +# AARCH64_QEMU = \ +# qemu-system-aarch64 \ +# -M raspi3 \ +# -nographic \ +# -kernel build/kernel/kernel.elf \ +# -serial stdio \ +# -monitor none \ +# vim:ft=make +# diff --git a/aarch64/boot.s b/aarch64/boot.s deleted file mode 100644 index fd6ebf5..0000000 --- a/aarch64/boot.s +++ /dev/null @@ -1,18 +0,0 @@ - .globl _start - -_start: - - mrs x0, mpidr_el1 // Check CPU ID - mov x1, 0xC1000000 - bic x0, x0, x1 - cbz x0, set_stack - b idle - -set_stack: - ldr x30, =stack_ptr // defined in sys/memmap - mov sp, x30 - bl k_main - -idle: - b idle - diff --git a/kernel/Makefile b/kernel/Makefile new file mode 100644 index 0000000..dd2d187 --- /dev/null +++ b/kernel/Makefile @@ -0,0 +1,63 @@ +# environment + +include ../Makevars.mk + +# CFLAGS + +CFLAGS += -O0 +CFLAGS += -g +CFLAGS += -nostdlib +CFLAGS += -march=armv8-a +# CFLAGS += -std=c99 +# CFLAGS += -pedantic +CFLAGS += -Wall +CFLAGS += -Wmissing-prototypes +CFLAGS += -Wstrict-prototypes +CFLAGS += -Wold-style-definition + +INCS += -I./ + +# SOURCES + +LD_SCRIPT = aarch64/aarch64.ld + +SOURCE_FILES = \ + aarch64/boot.S \ + aarch64/aarch64.S \ + \ + core/main.c \ + core/irq.c \ + core/timer.c \ + core/log.c \ + \ + device/uart/uart_mini.c \ + device/uart/uart_qemu.c \ + +SOURCE_LIST := $(wildcard $(SOURCE_FILES)) +OBJECT_FILES := $(addsuffix .o, $(addprefix $(BUILD_DIR), ${SOURCE_LIST})) + +# rules + +all: kernel + +default: kernel + +kernel: $(BUILD_DIR)kernel.elf + +$(BUILD_DIR)kernel.elf: $(OBJECT_FILES) + $(info linking target: $@) + $(AARCH64_LD) -T$(LD_SCRIPT) -nostdlib $^ -o $@ + $(info done: $@) + +$(BUILD_DIR)kernel.bin: $(BUILD_DIR)/kernel.elf + $(AARCH64_OBJCOPY) -O binary $< $@ + +$(BUILD_DIR)kernel.sym: $(BUILD_DIR)/kernel.elf + $(AARCH64_OBJCOPY) --only-keep-debug $< $@ + $(AARCH64_OBJCOPY) --strip-debug $@ + +$(BUILD_DIR)%.o: % + $(info compiling file: $<) + @mkdir -p $(dir ./$(BUILD_DIR)$<) + $(AARCH64_CC) $(INCS) $(CFLAGS) -c $< -o $@ + diff --git a/kernel/aarch64/aarch64.S b/kernel/aarch64/aarch64.S new file mode 100644 index 0000000..7d66884 --- /dev/null +++ b/kernel/aarch64/aarch64.S @@ -0,0 +1,181 @@ +#include "aarch64_irq.h" + +.globl aarch64_init +aarch64_init: + /* set vector table */ + adr x0, aarch64_vectors + msr vbar_el1, x0 + mov x0, 0 + ret + +.globl aarch64_get_el +aarch64_get_el: + mrs x0, CurrentEL + lsr x0, x0, 0x02 + ret + +.globl aarch64_get32r +aarch64_get32r: + ldr w0, [x0] + ret + +.globl aarch64_set32r +aarch64_set32r: + str w1, [x0] + ret + +.globl aarch64_delay +aarch64_delay: + subs x0, x0, 0x01 + bne aarch64_delay + ret + +.globl aarch64_irq_vector_init +irq_vector_init: + ret + +.globl aarch64_irq_enable +aarch64_irq_enable: + msr daifclr, 2 + ret + +.globl aarch64_irq_disable +aarch64_irq_disable: + msr daifset, 2 + ret + + +/* Exceptions Vector Table + * */ + .macro KERNEL_ENTER + sub sp, sp, 256 + stp x0, x1, [sp, 16 * 0] + stp x2, x3, [sp, 16 * 1] + stp x4, x5, [sp, 16 * 2] + stp x6, x7, [sp, 16 * 3] + stp x8, x9, [sp, 16 * 4] + stp x10, x11, [sp, 16 * 5] + stp x12, x13, [sp, 16 * 6] + stp x14, x15, [sp, 16 * 7] + stp x16, x17, [sp, 16 * 8] + stp x18, x19, [sp, 16 * 9] + stp x20, x21, [sp, 16 * 10] + stp x22, x23, [sp, 16 * 11] + stp x24, x25, [sp, 16 * 12] + stp x26, x27, [sp, 16 * 13] + stp x28, x29, [sp, 16 * 14] + str x30, [sp, 16 * 15] + .endm + + .macro KERNEL_LEAVE + ldp x0, x1, [sp, 16 * 0] + ldp x2, x3, [sp, 16 * 1] + ldp x4, x5, [sp, 16 * 2] + ldp x6, x7, [sp, 16 * 3] + ldp x8, x9, [sp, 16 * 4] + ldp x10, x11, [sp, 16 * 5] + ldp x12, x13, [sp, 16 * 6] + ldp x14, x15, [sp, 16 * 7] + ldp x16, x17, [sp, 16 * 8] + ldp x18, x19, [sp, 16 * 9] + ldp x20, x21, [sp, 16 * 10] + ldp x22, x23, [sp, 16 * 11] + ldp x24, x25, [sp, 16 * 12] + ldp x26, x27, [sp, 16 * 13] + ldp x28, x29, [sp, 16 * 14] + ldr x30, [sp, 16 * 15] + add sp, sp, 256 + .endm + + .macro VECTOR_ENTRY GOTO_LABEL + .align 7 + b \GOTO_LABEL + .endm + + .macro EXCEPTION_FALLBACK EID + KERNEL_ENTER + mov x0, \EID + mrs x1, esr_el1 + mrs x2, elr_el1 + bl k_irq_fallback + b die + .endm + +die: + b die + +.align 11 +.globl aarch64_vectors +aarch64_vectors: + /* EL1t */ + VECTOR_ENTRY el1t_sync + VECTOR_ENTRY el1t_irq + VECTOR_ENTRY el1t_fiq + VECTOR_ENTRY el1t_error + /* EL1h */ + VECTOR_ENTRY el1h_sync + VECTOR_ENTRY el1h_irq + VECTOR_ENTRY el1h_fiq + VECTOR_ENTRY el1h_error + /* EL0 - 64bit */ + VECTOR_ENTRY el0_64_sync + VECTOR_ENTRY el0_64_irq + VECTOR_ENTRY el0_64_fiq + VECTOR_ENTRY el0_64_error + /* EL0 - 32bit */ + VECTOR_ENTRY el0_32_sync + VECTOR_ENTRY el0_32_irq + VECTOR_ENTRY el0_32_fiq + VECTOR_ENTRY el0_32_error + +el1t_sync: + EXCEPTION_FALLBACK EL1t_SYNC + +el1t_irq: + EXCEPTION_FALLBACK EL1t_IRQ + +el1t_fiq: + EXCEPTION_FALLBACK EL1t_FIQ + +el1t_error: + EXCEPTION_FALLBACK EL1t_ERROR + +el1h_sync: + EXCEPTION_FALLBACK EL1h_SYNC + +el1h_irq: + KERNEL_ENTER + bl k_irq_handler + KERNEL_LEAVE + eret + +el1h_fiq: + EXCEPTION_FALLBACK EL1h_FIQ + +el1h_error: + EXCEPTION_FALLBACK EL1h_ERROR + +el0_64_sync: + EXCEPTION_FALLBACK EL0_64_SYNC + +el0_64_irq: + EXCEPTION_FALLBACK EL0_64_IRQ + +el0_64_fiq: + EXCEPTION_FALLBACK EL0_64_FIQ + +el0_64_error: + EXCEPTION_FALLBACK EL0_64_ERROR + +el0_32_sync: + EXCEPTION_FALLBACK EL0_32_SYNC + +el0_32_irq: + EXCEPTION_FALLBACK EL0_32_IRQ + +el0_32_fiq: + EXCEPTION_FALLBACK EL0_32_FIQ + +el0_32_error: + EXCEPTION_FALLBACK EL0_32_ERROR + diff --git a/kernel/aarch64/aarch64.h b/kernel/aarch64/aarch64.h new file mode 100644 index 0000000..4564249 --- /dev/null +++ b/kernel/aarch64/aarch64.h @@ -0,0 +1,43 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file util.h + * @author Ilja Kartašov + * @brief + * + * @see https://lowenware.com/ + */ + +#ifndef AARCH64_H_F3AA8888_CEB3_4C16_9835_C3F23B040BB5 +#define AARCH64_H_F3AA8888_CEB3_4C16_9835_C3F23B040BB5 + +#include "aarch64_reg.h" +#include "aarch64_irq.h" + +extern unsigned int +aarch64_init(void); + +extern unsigned int +aarch64_get_el(void); + +extern unsigned int +aarch64_get32r(unsigned long reg); + +extern void +aarch64_set32r(unsigned long reg, unsigned int value); + +extern void +aarch64_delay(unsigned long cycles); + +extern void +aarch64_irq_enable(void); + +extern void +aarch64_irq_disable(void); + +#endif /* !AARCH64_H */ diff --git a/aarch64/memmap b/kernel/aarch64/aarch64.ld similarity index 100% rename from aarch64/memmap rename to kernel/aarch64/aarch64.ld diff --git a/kernel/aarch64/aarch64_irq.h b/kernel/aarch64/aarch64_irq.h new file mode 100644 index 0000000..86b9ea9 --- /dev/null +++ b/kernel/aarch64/aarch64_irq.h @@ -0,0 +1,37 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file aarch64_irq.h + * @author Ilja Kartašov + * @brief + * + * @see https://lowenware.com/ + */ + +#ifndef AARCH64_IRQ_H_286AEC6E_325F_469E_B140_53DDDD63876C +#define AARCH64_IRQ_H_286AEC6E_325F_469E_B140_53DDDD63876C + +#define EL1t_SYNC 0 +#define EL1t_IRQ 1 +#define EL1t_FIQ 2 +#define EL1t_ERROR 3 +#define EL1h_SYNC 4 +#define EL1h_IRQ 5 +#define EL1h_FIQ 6 +#define EL1h_ERROR 7 +#define EL0_64_SYNC 8 +#define EL0_64_IRQ 9 +#define EL0_64_FIQ 10 +#define EL0_64_ERROR 11 +#define EL0_32_SYNC 12 +#define EL0_32_IRQ 13 +#define EL0_32_FIQ 14 +#define EL0_32_ERROR 15 + + +#endif /* !AARCH64_IRQ_H */ diff --git a/kernel/aarch64/aarch64_reg.h b/kernel/aarch64/aarch64_reg.h new file mode 100644 index 0000000..30a6ef4 --- /dev/null +++ b/kernel/aarch64/aarch64_reg.h @@ -0,0 +1,59 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file aarch64_reg.h + * @author Ilja Kartašov + * @brief + * + * @see https://lowenware.com/ + */ + +#ifndef AARCH64_REG_H_C74FE7BF_C8A6_4718_867A_C125CBF326BD +#define AARCH64_REG_H_C74FE7BF_C8A6_4718_867A_C125CBF326BD + +/* Saved Program Status Register (SPSR) + * Exception Level 3 (EL3) + * See page 389 of AArch64-Reference-Manual + * */ +#define SPSR_MASK_ALL (7 << 6) +#define SPSR_EL1h (5 << 0) +#define SPSR_VALUE (SPSR_MASK_ALL | SPSR_EL1h) + +/* Secure Configuration Register (SCR) + * Exception Level 3 (EL3) + * See page 2648 of AArch64-Reference-Manual + * */ +#define SCR_RESERVED (3 << 4) +#define SCR_RW (1 << 10) +#define SCR_NS (1 << 0) +#define SCR_VALUE (SCR_RESERVED | SCR_RW | SCR_NS) + +/* Hypervisor Configuration Register (HCR) + * Exception Level 2 (EL2) + * See page 2487 of AArch64-Reference-Manual + * */ +#define HCR_RW (1 << 31) +#define HCR_VALUE HCR_RW + +/* System Control REgister (SCTLR_EL1) + * Exception Level 1 (EL1) + * See page 2654 of AArch64-Reference-Manual + * */ +#define SCTLR_RESERVED (3 << 28) | (3 << 22) | (1 << 20) | (1 << 11) +#define SCTLR_EE_LITTLE_ENDIAN (0 << 25) +#define SCTLR_EOE_LITTLE_ENDIAN (0 << 24) +#define SCTLR_I_CACHE_DISABLED (0 << 12) +#define SCTLR_D_CACHE_DISABLED (0 << 2) +#define SCTLR_MMU_DISABLED (0 << 0) +#define SCTLR_MMU_ENABLED (1 << 0) + +#define SCTLR_VALUE_MMU_DISABLED (SCTLR_RESERVED | SCTLR_EE_LITTLE_ENDIAN \ + | SCTLR_I_CACHE_DISABLED | SCTLR_D_CACHE_DISABLED | SCTLR_MMU_DISABLED) + + +#endif /* !AARCH64_REG_H */ diff --git a/kernel/aarch64/bcm2837.h b/kernel/aarch64/bcm2837.h new file mode 100644 index 0000000..bfc1099 --- /dev/null +++ b/kernel/aarch64/bcm2837.h @@ -0,0 +1,74 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file bcm2837.h + * @author Ilja Kartašov + * @brief + * + * @see https://lowenware.com/ + */ + +#ifndef BCM2837_H_13CD1DB9_AAD7_4F1C_8669_37DED77135D1 +#define BCM2837_H_13CD1DB9_AAD7_4F1C_8669_37DED77135D1 + +#define PERIPHERAL_BASE 0x3F000000 + +/* GPIO */ +#define GPFSEL1 (PERIPHERAL_BASE + 0x00200004) +#define GPSET0 (PERIPHERAL_BASE + 0x0020001C) +#define GPCLR0 (PERIPHERAL_BASE + 0x00200028) +#define GPPUD (PERIPHERAL_BASE + 0x00200094) +#define GPPUDCLK0 (PERIPHERAL_BASE + 0x00200098) + +/* UART MINI */ +#define AUX_ENABLES (PERIPHERAL_BASE + 0x00215004) +#define AUX_MU_IO_REG (PERIPHERAL_BASE + 0x00215040) +#define AUX_MU_IER_REG (PERIPHERAL_BASE + 0x00215044) +#define AUX_MU_IIR_REG (PERIPHERAL_BASE + 0x00215048) +#define AUX_MU_LCR_REG (PERIPHERAL_BASE + 0x0021504C) +#define AUX_MU_MCR_REG (PERIPHERAL_BASE + 0x00215050) +#define AUX_MU_LSR_REG (PERIPHERAL_BASE + 0x00215054) +#define AUX_MU_MSR_REG (PERIPHERAL_BASE + 0x00215058) +#define AUX_MU_SCRATCH (PERIPHERAL_BASE + 0x0021505C) +#define AUX_MU_CNTL_REG (PERIPHERAL_BASE + 0x00215060) +#define AUX_MU_STAT_REG (PERIPHERAL_BASE + 0x00215064) +#define AUX_MU_BAUD_REG (PERIPHERAL_BASE + 0x00215068) + +/* IRQ */ +#define IRQ_BASIC_PENDING (PERIPHERAL_BASE + 0x0000B200) +#define IRQ_PENDING_1 (PERIPHERAL_BASE + 0x0000B204) +#define IRQ_PENDING_2 (PERIPHERAL_BASE + 0x0000B208) +#define FIQ_CONTROL (PERIPHERAL_BASE + 0x0000B20C) +#define ENABLE_IRQS_1 (PERIPHERAL_BASE + 0x0000B210) +#define ENABLE_IRQS_2 (PERIPHERAL_BASE + 0x0000B214) +#define ENABLE_BASIC_IRQS (PERIPHERAL_BASE + 0x0000B218) +#define DISABLE_IRQS_1 (PERIPHERAL_BASE + 0x0000B21C) +#define DISABLE_IRQS_2 (PERIPHERAL_BASE + 0x0000B220) +#define DISABLE_BASIC_IRQS (PERIPHERAL_BASE + 0x0000B224) + +/* SYSTEM TIMER */ +#define SYSTEM_TIMER_IRQ_0 (1 << 0) +#define SYSTEM_TIMER_IRQ_1 (1 << 1) +#define SYSTEM_TIMER_IRQ_2 (1 << 2) +#define SYSTEM_TIMER_IRQ_3 (1 << 3) + +/* TIMER */ +#define TIMER_CS (PERIPHERAL_BASE + 0x00003000) +#define TIMER_CLO (PERIPHERAL_BASE + 0x00003004) +#define TIMER_CHI (PERIPHERAL_BASE + 0x00003008) +#define TIMER_C0 (PERIPHERAL_BASE + 0x0000300C) +#define TIMER_C1 (PERIPHERAL_BASE + 0x00003010) +#define TIMER_C2 (PERIPHERAL_BASE + 0x00003014) +#define TIMER_C3 (PERIPHERAL_BASE + 0x00003018) + +#define TIMER_CS_M0 (1 << 0) +#define TIMER_CS_M1 (1 << 1) +#define TIMER_CS_M2 (1 << 2) +#define TIMER_CS_M3 (1 << 3) + +#endif /* !BCM2837_H */ diff --git a/kernel/aarch64/boot.S b/kernel/aarch64/boot.S new file mode 100644 index 0000000..5ee0ca4 --- /dev/null +++ b/kernel/aarch64/boot.S @@ -0,0 +1,41 @@ + +#include "aarch64_reg.h" + + .globl _start + +_start: + mrs x0, mpidr_el1 /* Check CPU ID */ + mov x1, 0xC1000000 + bic x0, x0, x1 + cbz x0, set_el +idle: + b idle + +set_el: + /* check current exception level */ + bl aarch64_get_el + cmp x0, 0x03 + bne set_stack + /* set SCTRL_EL1 */ + ldr x0, =SCTLR_VALUE_MMU_DISABLED + msr sctlr_el1, x0 + /* set HCR_EL2 */ + ldr x0, =HCR_VALUE + msr hcr_el2, x0 + /* set SCR_EL3 */ + ldr x0, =SCR_VALUE + msr scr_el3, x0 + /* set SPSR_EL3 */ + ldr x0, =SPSR_VALUE + msr spsr_el3, x0 + /* set elr_el3 */ + adr x0, set_stack + msr elr_el3, x0 + eret + +set_stack: + ldr x30, =stack_ptr /* defined in aarch64.ld */ + mov sp, x30 + bl k_main + + diff --git a/kernel/core/arch.h b/kernel/core/arch.h new file mode 100644 index 0000000..30ab40d --- /dev/null +++ b/kernel/core/arch.h @@ -0,0 +1,23 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file arch.h + * @author Ilja Kartašov + * @brief + * + * @see https://lowenware.com/ + */ + +#ifndef ARCH_H_F63C116D_51C9_4E25_9B1F_126833937268 +#define ARCH_H_F63C116D_51C9_4E25_9B1F_126833937268 + +#include + +#define k_arch_init(...) aarch64_init(__VA_ARGS__) + +#endif /* !ARCH_H */ diff --git a/kernel/core/irq.c b/kernel/core/irq.c new file mode 100644 index 0000000..888bf9a --- /dev/null +++ b/kernel/core/irq.c @@ -0,0 +1,71 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file irq.c + * @author Ilja Kartašov + * @brief + * + * @see https://lowenware.com/ + */ + +#include +#include "timer.h" +#include "log.h" +#include "irq.h" + +static const char *m_types[] = { + "EL1t_SYNC", + "EL1t_IRQ", + "EL1t_FIQ", + "EL1t_ERROR", + "EL1h_SYNC", + "EL1h_IRQ", + "EL1h_FIQ", + "EL1h_ERROR", + "EL0_64_SYNC", + "EL0_64_IRQ", + "EL0_64_FIQ", + "EL0_64_ERROR", + "EL0_32_SYNC", + "EL0_32_IRQ", + "EL0_32_FIQ", + "EL0_32_ERROR" +}; + +void +k_irq_enable_controller() +{ + aarch64_set32r(ENABLE_IRQS_1, SYSTEM_TIMER_IRQ_1); +} + +void +k_irq_handler(void) +{ + unsigned int irq = aarch64_get32r(IRQ_PENDING_1); + switch(irq) { + case SYSTEM_TIMER_IRQ_1: + k_timer_irq_handler(); + break; + + default: + k_logs("Unhandled irq: "); + k_logu(irq, 16); + k_logs("\n"); + } +} + +void +k_irq_fallback(int type, unsigned long esr, unsigned long address) +{ + k_logs(m_types[type]); + k_logs(" -> ESR: "); + k_logu(esr, 16); + k_logs(", address: "); + k_logu(address, 16); + k_logs("\n"); +} diff --git a/kernel/core/irq.h b/kernel/core/irq.h new file mode 100644 index 0000000..6302656 --- /dev/null +++ b/kernel/core/irq.h @@ -0,0 +1,34 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file irq.h + * @author Ilja Kartašov + * @brief + * + * @see https://lowenware.com/ + */ + +#ifndef IRQ_H_037ADD8D_3AAA_4541_A876_843DFF3A59E8 +#define IRQ_H_037ADD8D_3AAA_4541_A876_843DFF3A59E8 + +#include + +void +k_irq_enable_controller(void); + +void +k_irq_handler(void); + +void +k_irq_fallback(int type, unsigned long esr, unsigned long address); + +#define k_irq_enable(...) aarch64_irq_enable(__VA_ARGS__) + +#define k_irq_disable(...) aarch64_irq_disable(__VA_ARGS__) + +#endif /* !IRQ_H */ diff --git a/kernel/core/log.c b/kernel/core/log.c new file mode 100644 index 0000000..d1379e0 --- /dev/null +++ b/kernel/core/log.c @@ -0,0 +1,81 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file log.c + * @author Ilja Kartašov + * @brief + * + * @see https://lowenware.com/ + */ + +#include +#include "log.h" + +void +k_log_init(void) +{ + uart_init(); +} + +Ki32 +k_logs(const Ki8 *string) +{ + Ki8 c; + const Ki8 *p = string; + while((c = *p) != 0) { + if (uart_write(c)) + return -1; + p++; + } + return (Ki32)(p - string); +} + +Ki32 +k_logi(Ki64 value, Ku8 base) +{ + Ki32 result; + + if (value < 0) { + if (uart_write('-')) + return -1; + value = -value; + result = 1; + } else { + result = 0; + } + result += k_logu(value, base); + return (result) ? result : -1; +} + +Ki32 +k_logu(Ku64 value, Ku8 base) +{ + Ki32 i = 0, result; + Ku8 buffer[64]; + + if (!value) { + return (uart_write('0')) ? -1 : 1; + } + + do { + if (!(i < (sizeof(buffer) / sizeof(buffer[0])))) + return -1; + + Ku64 r = value % base; + buffer[i++] = (r < 0x0A) ? '0' + r : 'A' + r - 0x0A; + value /= base; + } while (value); + + result = i; + + while (i--) { + if (uart_write(buffer[i])) + return -1; + } + return result; +} diff --git a/kernel/core/log.h b/kernel/core/log.h new file mode 100644 index 0000000..6afdd29 --- /dev/null +++ b/kernel/core/log.h @@ -0,0 +1,33 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file print.h + * @author Ilja Kartašov + * @brief + * + * @see https://lowenware.com/ + */ + +#ifndef LOG_H_AE38CD54_2822_47A5_AFB1_E785739FA01D +#define LOG_H_AE38CD54_2822_47A5_AFB1_E785739FA01D + +#include + +void +k_log_init(void); + +Ki32 +k_logs(const Ki8 *string); + +Ki32 +k_logi(Ki64 value, Ku8 base); + +Ki32 +k_logu(Ku64 value, Ku8 base); + +#endif /* !LOG_H */ diff --git a/kernel/core/main.c b/kernel/core/main.c new file mode 100644 index 0000000..0a78939 --- /dev/null +++ b/kernel/core/main.c @@ -0,0 +1,65 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file main.c + * @author Ilja Kartašov + * @brief + * + * @see https://lowenware.com/ + */ + +#include +#include +#include +#include + + + +void +k_main(void); + + +void +k_main(void) +{ + k_log_init(); + + k_logs("Starting Lowe OS (EL"); + k_logi(aarch64_get_el(), 10); + k_logs(")\n"); + + if (k_arch_init()) + goto panic; + + k_timer_init(); + k_irq_enable_controller(); + k_irq_enable(); + + goto ok; + /* + k_logs("\tclock"); + if (k_clock_init()) + goto panic; + + k_logs(" - ok\n\tscheduler"); + if (k_scheduler_init()) + goto panic; + + k_logs(" - ok\n"); + + k_scheduler_run(); +*/ + +panic: + k_logs(" - ERROR\n"); +ok: + for (;;) { + __asm__("WFE"); + } +} + diff --git a/kernel/core/task.h b/kernel/core/task.h new file mode 100644 index 0000000..66958e3 --- /dev/null +++ b/kernel/core/task.h @@ -0,0 +1,37 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file task.h + * @author Ilja Kartašov + * @brief + * + * @see https://lowenware.com/ + */ + +#ifndef TASK_H_AE13C166_79B5_4256_ABF3_74DF04E1CD18 +#define TASK_H_AE13C166_79B5_4256_ABF3_74DF04E1CD18 + +#include + +typedef Ku32 KTaskId; +typedef void (*KTaskCallback)(void *p_ctx); + +struct k_task { + KByte name[K_CONFIG_TASK_MAX_NAME_LEN + 1]; + KTaskCallback callback; + Ku32 *stack; + Ku32 stack_size; + Ku32 priority; +}; + +KTaskId +k_task_create(struct k_task *p_task, KTaskCallback callback, Ku32 *stack + , Ku32 stack_size); + + +#endif /* !TASK_H */ diff --git a/kernel/core/timer.c b/kernel/core/timer.c new file mode 100644 index 0000000..661a74c --- /dev/null +++ b/kernel/core/timer.c @@ -0,0 +1,39 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file timer.c + * @author Ilja Kartašov + * @brief + * + * @see https://lowenware.com/ + */ + +#include +#include +#include "timer.h" +#include "log.h" + +const unsigned int m_interval = 200000; +unsigned int m_current = 0; + +void +k_timer_init(void) +{ + m_current = aarch64_get32r(TIMER_CLO); + m_current += m_interval; + aarch64_set32r(TIMER_C1, m_current); +} + +void +k_timer_irq_handler(void) +{ + m_current += m_interval; + aarch64_set32r(TIMER_C1, m_current); + aarch64_set32r(TIMER_CS, TIMER_CS_M1); + k_logs("Timer interrupt\n"); +} diff --git a/sys/main.c b/kernel/core/timer.h similarity index 67% rename from sys/main.c rename to kernel/core/timer.h index 19b4ad4..389b254 100644 --- a/sys/main.c +++ b/kernel/core/timer.h @@ -6,29 +6,20 @@ ******************************************************************************/ /** - * @file main.c + * @file timer.h * @author Ilja Kartašov * @brief * * @see https://lowenware.com/ */ -#include "uart.h" - +#ifndef TIMER_H_8D327261_47D6_4832_8DC5_31BF1614A21F +#define TIMER_H_8D327261_47D6_4832_8DC5_31BF1614A21F void -k_main(void); - +k_timer_init(void); void -k_main(void) -{ - uart_init(); - - uart_puts((unsigned char *) "Lowe OS\n"); - - for (;;) { - __asm__("WFE"); - } -} +k_timer_irq_handler(void); +#endif /* !TIMER_H */ diff --git a/kernel/core/types.h b/kernel/core/types.h new file mode 100644 index 0000000..bfa27c1 --- /dev/null +++ b/kernel/core/types.h @@ -0,0 +1,29 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file types.h + * @author Ilja Kartašov + * @brief + * + * @see https://lowenware.com/ + */ + +#ifndef TYPES_H_BC3DA9C0_C9EE_4853_B5F5_EAA4B801664C +#define TYPES_H_BC3DA9C0_C9EE_4853_B5F5_EAA4B801664C + +typedef int KRetCode; + +typedef int Ki32; +typedef unsigned int Ku32; +typedef long long Ki64; +typedef unsigned long long Ku64; +typedef char Ki8; +typedef unsigned char Ku8; +typedef char KByte; + +#endif /* !TYPES_H */ diff --git a/kernel/device/uart/uart.h b/kernel/device/uart/uart.h new file mode 100644 index 0000000..a5a6825 --- /dev/null +++ b/kernel/device/uart/uart.h @@ -0,0 +1,47 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file uart.h + * @author Ilja Kartašov + * @brief + * + * @see https://lowenware.com/ + */ + +#ifndef UART_H_8AFC47F9_2953_42C1_A5C1_1AE5A1F52CD0 +#define UART_H_8AFC47F9_2953_42C1_A5C1_1AE5A1F52CD0 + +#include "uart_mini.h" +#include "uart_qemu.h" + +#define UART_MINI 0 +#define UART_QEMU 1 + +#ifndef UART_DEFAULT +#define UART_DEFAULT UART_QEMU +#endif + +#if UART_DEFAULT == UART_MINI + +#define uart_init(...) uart_mini_init(__VA_ARGS__) +#define uart_read(...) uart_mini_read(__VA_ARGS__) +#define uart_write(...) uart_mini_write(__VA_ARGS__) + +#elif UART_DEFAULT == UART_QEMU + +#define uart_init(...) +#define uart_read(...) +#define uart_write(...) uart_qemu_write(__VA_ARGS__) + +#else + +#warning "Unsopported default UART" + +#endif + +#endif /* !UART_H */ diff --git a/kernel/device/uart/uart_mini.c b/kernel/device/uart/uart_mini.c new file mode 100644 index 0000000..d616c19 --- /dev/null +++ b/kernel/device/uart/uart_mini.c @@ -0,0 +1,82 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file uart_mini.c + * @author Ilja Kartašov + * @brief + * + * @see https://lowenware.com/ + */ + +#include +#include + +#include "uart_mini.h" + + +int +uart_mini_init(void) +{ + unsigned int sel; + + /* Enable UART Mini and its registers*/ + aarch64_set32r(AUX_ENABLES, 1); + /* Disable auto flow control, TX and RX */ + aarch64_set32r(AUX_MU_CNTL_REG, 0); + /* Disable TX and RX interrupts */ + aarch64_set32r(AUX_MU_IER_REG, 0); + /* Set 8bit mode */ + aarch64_set32r(AUX_MU_LCR_REG, 0); + /* Set RTS line HIGH */ + aarch64_set32r(AUX_MU_MCR_REG, 0); + /* Set baud rate 115200 */ + aarch64_set32r(AUX_MU_BAUD_REG, 0x10E); + + sel = aarch64_get32r(GPFSEL1); + /* clean and set ALT5 for GPIO14 */ + sel &= ~(7 << 12); + sel |= (2 << 12); + /* clean and set ALT5 for GPIO15 */ + sel &= ~(7 << 15); + sel |= (2 << 15); + aarch64_set32r(GPFSEL1, sel); + + aarch64_set32r(GPPUD, 0); + aarch64_delay(150); + aarch64_set32r(GPPUDCLK0, (1 << 14) | (1 << 15)); + aarch64_delay(150); + aarch64_set32r(GPPUDCLK0, 0); + + /* Enable TX and RX */ + aarch64_set32r(AUX_MU_CNTL_REG, 0x03); + + return 0; +} + +int +uart_mini_write(char c) +{ + while (1) { + if (aarch64_get32r(AUX_MU_LSR_REG) & 0x20) + break; + } + aarch64_set32r(AUX_MU_IO_REG, c); + + return 0; +} + +int +uart_mini_read(char *pc) +{ + while (1) { + if (aarch64_get32r(AUX_MU_LSR_REG) & 0x01) + break; + } + *pc = aarch64_get32r(AUX_MU_IO_REG) & 0xFF; + return 0; +} diff --git a/sys/uart.h b/kernel/device/uart/uart_mini.h similarity index 59% rename from sys/uart.h rename to kernel/device/uart/uart_mini.h index 2c7c571..a801053 100644 --- a/sys/uart.h +++ b/kernel/device/uart/uart_mini.h @@ -6,28 +6,23 @@ ******************************************************************************/ /** - * @file uart.h + * @file uart_mini.h * @author Ilja Kartašov * @brief * * @see https://lowenware.com/ */ -#ifndef UART_H_8AFC47F9_2953_42C1_A5C1_1AE5A1F52CD0 -#define UART_H_8AFC47F9_2953_42C1_A5C1_1AE5A1F52CD0 +#ifndef UART_MINI_H_B0DFA3CF_5B4F_4EB0_B393_391C0069A04F +#define UART_MINI_H_B0DFA3CF_5B4F_4EB0_B393_391C0069A04F +int +uart_mini_init(void); -#define UART_BASE 0x09000000 +int +uart_mini_write(char c); -void -uart_init(void); +int +uart_mini_read(char *pc); - -void -uart_putc(unsigned char c); - - -void -uart_puts(const unsigned char *s); - -#endif /* !UART_H */ +#endif /* !UART_MINI_H */ diff --git a/sys/uart.c b/kernel/device/uart/uart_qemu.c similarity index 74% rename from sys/uart.c rename to kernel/device/uart/uart_qemu.c index da09b6c..147207a 100644 --- a/sys/uart.c +++ b/kernel/device/uart/uart_qemu.c @@ -13,29 +13,18 @@ * @see https://lowenware.com/ */ -#include "uart.h" +#include "uart_qemu.h" + +#define UART_BASE 0x09000000; volatile unsigned int *UART0 = (unsigned int *)UART_BASE; - -void -uart_init(void) -{ - -} - - -void -uart_putc(unsigned char c) +int +uart_qemu_write(unsigned char c) { *UART0 = (unsigned int) c; + return 0; } -void -uart_puts(const unsigned char *s) -{ - while(*s) { - *UART0 = (unsigned int) *(s++); - } -} + diff --git a/kernel/device/uart/uart_qemu.h b/kernel/device/uart/uart_qemu.h new file mode 100644 index 0000000..8f2fd81 --- /dev/null +++ b/kernel/device/uart/uart_qemu.h @@ -0,0 +1,22 @@ +/****************************************************************************** + * + * Copyright (c) 2017-2019 by Löwenware Ltd + * Please, refer LICENSE file for legal information + * + ******************************************************************************/ + +/** + * @file uart_qemu.h + * @author Ilja Kartašov + * @brief + * + * @see https://lowenware.com/ + */ + +#ifndef UART_QEMU_H_EDB39A0E_9BED_4A47_91CD_E804A9B4E8ED +#define UART_QEMU_H_EDB39A0E_9BED_4A47_91CD_E804A9B4E8ED + +int +uart_qemu_write(unsigned char c); + +#endif /* !UART_QEMU_H */ diff --git a/sys/core.s b/sys/core.s deleted file mode 100644 index 2fc6bdc..0000000 --- a/sys/core.s +++ /dev/null @@ -1,38 +0,0 @@ -# file: core.s -# project: Löwe OS -# authors: Elias Löwe - -# ----------------------------------------------------------------------------- - - .global _core_init - .extern _uart_puts - -# ----------------------------------------------------------------------------- - - .text - -_core_init: - # set up stack pointer using x30 register - LDR x30, =0x40001000 - MOV sp, x30 - bl 1f - -1: - LDR x0, =some_int - BL _uart_putx - LDR x0, =greeting - BL _uart_puts -2: - B 2b - -# ----------------------------------------------------------------------------- - - .data - -greeting: - .asciz "\nStarting Lowe OS\n" - - - .equ some_int, 0x1234567890ABCDEF - -# ----------------------------------------------------------------------------- diff --git a/sys/uart.s b/sys/uart.s deleted file mode 100644 index a5bece1..0000000 --- a/sys/uart.s +++ /dev/null @@ -1,93 +0,0 @@ -// file : uart.s -// project : Löwe OS -// authors : Elias Löwe - -// address of UART for virt device in qemu - -// ----------------------------------------------------------------------------- - - .global _uart_putc // print single character uart - .global _uart_putx // print integer in HEX format to uart - .global _uart_puts // print null-terminated string to uart - -// ----------------------------------------------------------------------------- - - .text - -// helper to avoid extra data moving -// @x1 character print -uart_putc: - STP x2, lr, [sp, -16]! - - MOV x2, 0x09000000 // set UART address - STRB w1, [x2] // put character out - - LDP x2, lr, [sp], 16 - RET - -// ----------------------------------------------------------------------------- - - -// print character to uart -// @x0 character print -_uart_putc: - STR lr, [sp, -16]! - - MOV x1, x0 // set arguments - BL uart_putc // put character out - - LDR lr, [sp], 16 - RET - - -// ----------------------------------------------------------------------------- - -// @x0 integer to print -_uart_putx: - STP lr, x3, [sp, -32]! - STP x0, x1, [sp, 16] - - LDR x3, =60 // init bits counter 64-4 - -1: - LSR x1, x0, x3 // shift to digit - AND x1, x1, 0xF // keep only digit - CMP x1, 9 // compare it to 9 - BLS 2f // less or equal - ADD x1, x1, 0x37 // turn into ASCII HEX char - B 3f // continue to output - -2: - ADD x1, x1, 0x30 // turn into ASCII num char - -3: - BL uart_putc // output carachter - CBZ x3, 0f // if counter == 0 return - SUB x3, x3, 4 // otherwise subtract counter by 4 - B 1b // repeat - -0: - LDP lr, x3, [sp], 16 - LDP x0, x1, [sp], 16 - RET - -// ----------------------------------------------------------------------------- - -// @x0 pointer to string - -_uart_puts: - STR lr, [sp, -16]! - STP x0, x1, [sp, -16]! - -1: - LDRB w1, [x0], 1 // load byte of string from address in x0 - CBZ w1, 0f // return if zero - BL uart_putc // put charcter out - B 1b // loop - -0: - LDP x0, x1, [sp], 16 - LDR lr, [sp], 16 - RET - -// -----------------------------------------------------------------------------