From 8e4f77bd9f6f8327b2541cf74f05d0ed23e95b78 Mon Sep 17 00:00:00 2001 From: Aaron Alef Date: Tue, 2 Nov 2021 09:51:10 +0100 Subject: [PATCH 01/21] feat(bulb): add bulb, an OS that solely relies on mailbox comms --- Makefile | 19 +- bulb/Makefile | 124 +++++++++++ bulb/include/common/debug.h | 16 ++ bulb/include/common/font.h | 36 ++++ bulb/include/common/gpu.h | 57 +++++ bulb/include/common/logging.h | 27 +++ bulb/include/common/printf.h | 107 ++++++++++ bulb/include/common/screen.h | 20 ++ bulb/include/common/status_led.h | 24 +++ bulb/include/common/stdbool.h | 10 + bulb/include/common/stddef.h | 10 + bulb/include/common/utils.h | 12 ++ bulb/include/kernel/arm/sysregs.h | 49 +++++ bulb/include/kernel/entry.h | 35 ++++ bulb/include/kernel/mailbox.h | 40 ++++ bulb/include/kernel/mm.h | 33 +++ bulb/include/kernel/mmu.h | 38 ++++ bulb/include/kernel/peripherals/base.h | 6 + bulb/include/kernel/peripherals/gpio.h | 12 ++ bulb/include/kernel/peripherals/gpu.h | 10 + bulb/include/kernel/peripherals/mailbox.h | 19 ++ bulb/src/common/debug.c | 29 +++ bulb/src/common/font.c | 195 +++++++++++++++++ bulb/src/common/gpu.c | 137 ++++++++++++ bulb/src/common/printf.c | 243 ++++++++++++++++++++++ bulb/src/common/screen.c | 14 ++ bulb/src/common/status_led.c | 55 +++++ bulb/src/common/utils.S | 21 ++ bulb/src/config.txt | 2 + bulb/src/kernel/boot.S | 52 +++++ bulb/src/kernel/kernel.c | 43 ++++ bulb/src/kernel/mailbox.c | 52 +++++ bulb/src/kernel/mm.S | 14 ++ bulb/src/kernel/mm.c | 19 ++ bulb/src/kernel/mmu.c | 134 ++++++++++++ bulb/src/linker.ld | 19 ++ 36 files changed, 1730 insertions(+), 3 deletions(-) create mode 100644 bulb/Makefile create mode 100644 bulb/include/common/debug.h create mode 100644 bulb/include/common/font.h create mode 100644 bulb/include/common/gpu.h create mode 100644 bulb/include/common/logging.h create mode 100644 bulb/include/common/printf.h create mode 100644 bulb/include/common/screen.h create mode 100644 bulb/include/common/status_led.h create mode 100644 bulb/include/common/stdbool.h create mode 100644 bulb/include/common/stddef.h create mode 100644 bulb/include/common/utils.h create mode 100644 bulb/include/kernel/arm/sysregs.h create mode 100644 bulb/include/kernel/entry.h create mode 100644 bulb/include/kernel/mailbox.h create mode 100644 bulb/include/kernel/mm.h create mode 100644 bulb/include/kernel/mmu.h create mode 100644 bulb/include/kernel/peripherals/base.h create mode 100644 bulb/include/kernel/peripherals/gpio.h create mode 100644 bulb/include/kernel/peripherals/gpu.h create mode 100644 bulb/include/kernel/peripherals/mailbox.h create mode 100644 bulb/src/common/debug.c create mode 100644 bulb/src/common/font.c create mode 100644 bulb/src/common/gpu.c create mode 100644 bulb/src/common/printf.c create mode 100644 bulb/src/common/screen.c create mode 100644 bulb/src/common/status_led.c create mode 100644 bulb/src/common/utils.S create mode 100644 bulb/src/config.txt create mode 100644 bulb/src/kernel/boot.S create mode 100644 bulb/src/kernel/kernel.c create mode 100644 bulb/src/kernel/mailbox.c create mode 100644 bulb/src/kernel/mm.S create mode 100644 bulb/src/kernel/mm.c create mode 100644 bulb/src/kernel/mmu.c create mode 100644 bulb/src/linker.ld diff --git a/Makefile b/Makefile index 09b3a90..1ee03d7 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ MNT_Darwin = /Volumes/boot #BOOT_PART = /dev/mmcblk0p1 # Serial connection config -SEND_DEFAULT_TARGET = thorn +SEND_DEFAULT_TARGET = bulb BAUD_RATE = 115200 SERIAL_PORT = $(SERIAL_PORT_$(HOST_OS)) SERIAL_PORT_ALT = $(SERIAL_PORT_ALT_$(HOST_OS)) @@ -22,7 +22,7 @@ SERIAL_PORT_Darwin = /dev/$(shell ls /dev | grep usbserial | head -n 2 | tai SERIAL_PORT_ALT_Darwin = /dev/$(shell ls /dev | grep usbserial | head -n 1) # Building -BUILD_DEFAULT_TARGET = thorn +BUILD_DEFAULT_TARGET = bulb # Ensure make still works if someone creates a file named like follows: .PHONY: all build clean flash resend send reboot poweroff @@ -35,11 +35,12 @@ clean: rm -rf $(BUILD) *.img $(MAKE) -C chainloader clean $(MAKE) -C thorn clean + $(MAKE) -C bulb clean # Build the different OSes build: build-$(BUILD_DEFAULT_TARGET) -buildall: build-chainloader build-thorn +buildall: build-chainloader build-thorn build-bulb build-chainloader: $(MAKE) -C chainloader build @@ -47,6 +48,9 @@ build-chainloader: build-thorn: $(MAKE) -C thorn build +build-bulb: + $(MAKE) -C bulb build + # Mount boot partition of SD card onto set mount point to copy image onto it flash: flash-$(FLASH_DEFAULT_TARGET) @@ -56,6 +60,9 @@ flash-chainloader: flash-thorn: $(MAKE) -C thorn flash +flash-bulb: + $(MAKE) -C bulb flash + # Send kernel size + kernel setup-serial-Linux: stty -F $(SERIAL_PORT) $(BAUD_RATE) raw cs8 -ixoff -cstopb -parenb @@ -77,6 +84,9 @@ send-chainloader: setup-serial-$(HOST_OS) send-thorn: setup-serial-$(HOST_OS) $(MAKE) -C thorn send +send-bulb: setup-serial-$(HOST_OS) + $(MAKE) -C bulb send + # Set up screen on alternate serial port screen: screen $(SERIAL_PORT_ALT) $(BAUD_RATE) @@ -99,3 +109,6 @@ emulate-chainloader: emulate-thorn: $(MAKE) -C thorn emulate +emulate-bulb: + $(MAKE) -C bulb emulate + diff --git a/bulb/Makefile b/bulb/Makefile new file mode 100644 index 0000000..e510523 --- /dev/null +++ b/bulb/Makefile @@ -0,0 +1,124 @@ +# | Makefile for the Rose project (github.com/anarchuser/rose) +# | Merged from https://jsandler18.github.io/ and https://github.com/s-matyukevich/raspberry-pi-os + +# Cross-compiler +ARMGNU ?= aarch64-none-elf + +# Resolve Mac / linux issues +HOST_OS = $(shell uname -s) + +# Build target +IMAGE_NAME = $(shell basename `pwd`) + +# Options for C, Asembly, and the linker, respectively +COPS = -Wall -nostdlib -nostartfiles -ffreestanding -Iinclude -mgeneral-regs-only +ASMOPS = -Iinclude +LOPS = -ffreestanding -nostdlib + +# Mount point and boot partition +MNT = $(MNT_$(HOST_OS)) +MNT_Linux = ../mnt +MNT_Darwin = /Volumes/boot + +# Serial connection config +BAUD_RATE = 115200 +SERIAL_PORT = $(SERIAL_PORT_$(HOST_OS)) +SERIAL_PORT_Linux = /dev/$(shell ls /dev | grep ttyUSB | head -n 2 | tail -n 1) +SERIAL_PORT_Darwin = /dev/$(shell ls /dev | grep usbserial | head -n 2 | tail -n 1) + +# Directories for built files, source files (kernel and common) and header files (include) +BUILD = build +SRC = src +KERNEL = kernel +COMMON = common +INCLUDE = include + +# Assemble lists of corresponding source files for assembly, kernel and common +SRC_KERNEL = $(wildcard $(SRC)/$(KERNEL)/*.c) +ASM_KERNEL = $(wildcard $(SRC)/$(KERNEL)/*.S) +SRC_COMMON = $(wildcard $(SRC)/$(COMMON)/*.c) +ASM_COMMON = $(wildcard $(SRC)/$(COMMON)/*.S) + +# Assemble list of compiled objects, correspondingly +OBJECTS = $(patsubst $(SRC)/$(KERNEL)/%.c, $(BUILD)/$(SRC)/$(KERNEL)/%_c.o, $(SRC_KERNEL)) +OBJECTS += $(patsubst $(SRC)/$(KERNEL)/%.S, $(BUILD)/$(SRC)/$(KERNEL)/%_S.o, $(ASM_KERNEL)) +OBJECTS += $(patsubst $(SRC)/$(COMMON)/%.c, $(BUILD)/$(SRC)/$(COMMON)/%_c.o, $(SRC_COMMON)) +OBJECTS += $(patsubst $(SRC)/$(COMMON)/%.S, $(BUILD)/$(SRC)/$(COMMON)/%_S.o, $(ASM_COMMON)) + +# Ensure make still works if someone creates a file named like follows: +.PHONY: build clean flash flash-Linux flash-Darwin emulate reboot poweroff send resend + +# Default target (invoked by `make` or `make build`). +build: $(IMAGE_NAME).img + +# Build kernel executable and linkable file where we can extract the kernel from +$(IMAGE_NAME).elf: $(OBJECTS) $(SRC)/linker.ld + $(ARMGNU)-ld -T $(SRC)/linker.ld -o $(BUILD)/$(IMAGE_NAME).elf $(OBJECTS) + +# Build actual kernel image +$(IMAGE_NAME).img: $(SRC)/linker.ld $(OBJECTS) $(IMAGE_NAME).elf + $(ARMGNU)-objcopy $(BUILD)/$(IMAGE_NAME).elf -O binary $(IMAGE_NAME).img + +# All kernel source targets +$(BUILD)/$(SRC)/$(KERNEL)/%_c.o: $(SRC)/$(KERNEL)/%.c + mkdir -p $(@D) + $(ARMGNU)-gcc $(COPS) -MMD -c $< -o $@ + +# All assembly source targets +$(BUILD)/$(SRC)/$(KERNEL)/%_S.o: $(SRC)/$(KERNEL)/%.S + mkdir -p $(@D) + $(ARMGNU)-gcc $(ASMOPS) -MMD -c $< -o $@ + +# All common source targets +$(BUILD)/$(SRC)/$(COMMON)/%_c.o: $(SRC)/$(COMMON)/%.c + mkdir -p $(@D) + $(ARMGNU)-gcc $(COPS) -MMD -c $< -o $@ + +# All assembly source targets +$(BUILD)/$(SRC)/$(COMMON)/%_S.o: $(SRC)/$(COMMON)/%.S + mkdir -p $(@D) + $(ARMGNU)-gcc $(ASMOPS) -MMD -c $< -o $@ + +# Compile lists with the dependencies between objects +DEP_FILES = $(OBJECTS:%.o=%.d) + -include $(DEP_FILES) + +# Remove kernel and build directory +clean: + rm -rf $(BUILD) *.img + +# Mount boot partition of SD card onto set mount point to copy image onto it +flash: flash-$(HOST_OS) + +flash-Linux: $(IMAGE_NAME).img + mkdir -p $(MNT) + mount $(MNT) + cp $(IMAGE_NAME).img $(MNT)/kernel8.img + cp $(SRC)/config.txt $(MNT) + sync + sleep 1 + umount $(MNT) + +flash-Darwin: $(IMAGE_NAME).img + cp $(IMAGE_NAME).img $(MNT)/kernel8.img + cp $(SRC)/config.txt $(MNT) + sync + diskutil unmount $(MNT) + +resend: reboot send + +send: $(IMAGE_NAME).img + printf "0: %.8x" $(shell wc -c < $(IMAGE_NAME).img) | xxd -r -g0 > $(SERIAL_PORT) + cat $(IMAGE_NAME).img > $(SERIAL_PORT) + +# Run on qemu +emulate: $(IMAGE_NAME).img + qemu-img resize $(IMAGE_NAME).img -f raw 4294967296 + qemu-system-aarch64 -cpu cortex-a72 -machine type=raspi3 -m 1024 -kernel $(IMAGE_NAME).img -nographic -serial null -chardev stdio,id=uart1 -serial chardev:uart1 -monitor none + +poweroff: + $(MAKE) -C .. poweroff + +reboot: + $(MAKE) -C .. reboot + diff --git a/bulb/include/common/debug.h b/bulb/include/common/debug.h new file mode 100644 index 0000000..99e2ec3 --- /dev/null +++ b/bulb/include/common/debug.h @@ -0,0 +1,16 @@ +#ifndef _ROSE_C_DEBUG_H +#define _ROSE_DEBUG_H + +#include "common/logging.h" +#include "common/printf.h" +#include "common/stddef.h" + +#define CHECKPOINT LOG ("Checkpoint"); + +void print_hex (unsigned char dec); + +void hex_dump (byte_t * array); + +void int_dump (unsigned int * array); + +#endif//_ROSE_C_DEBUG_H \ No newline at end of file diff --git a/bulb/include/common/font.h b/bulb/include/common/font.h new file mode 100644 index 0000000..5b49ada --- /dev/null +++ b/bulb/include/common/font.h @@ -0,0 +1,36 @@ +#ifndef _ROSE_C_FONT_H +#define _ROSE_C_FONT_H + +#define FONT_SIZE 8 +#define FONT_FACTOR 2 +#define FONT_REAL_WIDTH (FONT_SIZE * FONT_FACTOR) + +// Spacing between lines in pixels +#define FONT_SPACING 4 +#define FONT_REAL_HEIGHT (FONT_REAL_WIDTH + FONT_SPACING) + +// Width of horizontal tabs in characters +#define FONT_TAB_SIZE 4 +#define FONT_TAB_REAL_WIDTH (FONT_TAB_SIZE * FONT_REAL_WIDTH) + +#include "common/gpu.h" +#include "common/screen.h" + +static point_t cursor = {0, 0}; + +static volatile color_t font_bg = {0x00, 0x00, 0x00, 0x00}; +static volatile color_t font_normal_fg = {0xC0, 0xC0, 0xC0, 0x00}; +static volatile color_t font_error_fg = {0x00, 0x00, 0xC0, 0x00}; +static volatile color_t font_fg; + +const unsigned long long int * font (int c); + +void printc (char c); +void printc_location (point_t point, char c); + +void putc_screen (void * p, char c); + +void font_set_normal (void); +void font_set_error (void); + +#endif diff --git a/bulb/include/common/gpu.h b/bulb/include/common/gpu.h new file mode 100644 index 0000000..1237103 --- /dev/null +++ b/bulb/include/common/gpu.h @@ -0,0 +1,57 @@ +#ifndef _ROSE_C_GPU_H +#define _ROSE_C_GPU_H + +#include "common/printf.h" + +#include "common/stdbool.h" +#include "common/stddef.h" +#include "kernel/mailbox.h" +#include "kernel/mm.h" +#include "kernel/peripherals/gpu.h" + +// Reference: +// https://jsandler18.github.io/extra/prop-channel.html + +// Uncomment to override physical / virtual screen size with the values defined below +#define GPU_OVERRIDE_PHYSICAL_SCREEN + +#define GPU_SCREEN_WIDTH 1920// Width used if Override is enabled +#define GPU_SCREEN_HEIGHT 1080// Height used if Override is enabled + +#define GPU_VIRTUAL_WIDTH GPU_SCREEN_WIDTH +#define GPU_VIRTUAL_HEIGHT GPU_SCREEN_HEIGHT + +#define GPU_COLOUR_DEPTH 32 + +#define VC_SDRAM_OFFSET 0x3FFFFFFF + +typedef struct { + byte_t blue; + byte_t green; + byte_t red; + byte_t alpha; +} color_t; + +typedef struct { + color_t * fb; + unsigned int fb_size; + short virtual_width; + short virtual_height; + short pitch; + short colour_depth; +} fb_info_t; + +static volatile unsigned int __attribute__ ((aligned (16))) gpu_msg_buffer[128]; + +static fb_info_t fb_info; + +bool init_gpu (void); + +color_t * get_fb (void); + +fb_info_t const * get_fb_info (void); + +bool blank_screen (bool blank); +bool toggle_blank_screen (void); + +#endif//_ROSE_C_GPU_H \ No newline at end of file diff --git a/bulb/include/common/logging.h b/bulb/include/common/logging.h new file mode 100644 index 0000000..6203d6b --- /dev/null +++ b/bulb/include/common/logging.h @@ -0,0 +1,27 @@ +#ifndef _ROSE_C_LOGGING_H +#define _ROSE_C_LOGGING_H + +#include "common/printf.h" + +#define LOG(msg) \ + do { \ + static int __counter__ = 0; \ + printf (__FILE__ ":%d:[%d] %s\r\n", __LINE__, __counter__++, msg); \ + } while (0) + +#define ERROR(msg) \ + do { \ + static int __counter__ = 0; \ + font_set_error (); \ + printf (__FILE__ ":%d:[%d] %s\r\n", __LINE__, __counter__++, msg); \ + font_set_normal (); \ + } while (0) + +#define ASSERT(expr) \ + do { \ + if (! (expr)) \ + LOG ("Assertion failed"); \ + } while (0) + + +#endif /*_ROSE_C_LOGGING_H*/ diff --git a/bulb/include/common/printf.h b/bulb/include/common/printf.h new file mode 100644 index 0000000..382087b --- /dev/null +++ b/bulb/include/common/printf.h @@ -0,0 +1,107 @@ +/* +File: printf.h + +Copyright (C) 2004 Kustaa Nyholm + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +This library is really just two files: 'printf.h' and 'printf.c'. + +They provide a simple and small (+200 loc) printf functionality to +be used in embedded systems. + +I've found them so usefull in debugging that I do not bother with a +debugger at all. + +They are distributed in source form, so to use them, just compile them +into your project. + +Two printf variants are provided: printf and sprintf. + +The formats supported by this implementation are: 'd' 'u' 'c' 's' 'x' 'X'. + +Zero padding and field width are also supported. + +If the library is compiled with 'PRINTF_SUPPORT_LONG' defined then the +long specifier is also +supported. Note that this will pull in some long math routines (pun intended!) +and thus make your executable noticably longer. + +The memory foot print of course depends on the target cpu, compiler and +compiler options, but a rough guestimate (based on a H8S target) is about +1.4 kB for code and some twenty 'int's and 'char's, say 60 bytes of stack space. +Not too bad. Your milage may vary. By hacking the source code you can +get rid of some hunred bytes, I'm sure, but personally I feel the balance of +functionality and flexibility versus code size is close to optimal for +many embedded systems. + +To use the printf you need to supply your own character output function, +something like : + + void putc ( void* p, char c) + { + while (!SERIAL_PORT_EMPTY) ; + SERIAL_PORT_TX_REGISTER = c; + } + +Before you can call printf you need to initialize it to use your +character output function with something like: + + init_printf(NULL,putc); + +Notice the 'NULL' in 'init_printf' and the parameter 'void* p' in 'putc', +the NULL (or any pointer) you pass into the 'init_printf' will eventually be +passed to your 'putc' routine. This allows you to pass some storage space (or +anything really) to the character output function, if necessary. +This is not often needed but it was implemented like that because it made +implementing the sprintf function so neat (look at the source code). + +The code is re-entrant, except for the 'init_printf' function, so it +is safe to call it from interupts too, although this may result in mixed output. +If you rely on re-entrancy, take care that your 'putc' function is re-entrant! + +The printf and sprintf functions are actually macros that translate to +'tfp_printf' and 'tfp_sprintf'. This makes it possible +to use them along with 'stdio.h' printf's in a single source file. +You just need to undef the names before you include the 'stdio.h'. +Note that these are not function like macros, so if you have variables +or struct members with these names, things will explode in your face. +Without variadic macros this is the best we can do to wrap these +fucnction. If it is a problem just give up the macros and use the +functions directly or rename them. + +For further details see source code. + +regs Kusti, 23.10.2004 +*/ + + +#ifndef __TFP_PRINTF__ +#define __TFP_PRINTF__ + +#include + +void init_printf (void * putp, void (*putf) (void *, char)); + +void tfp_printf (char * fmt, ...); + +void tfp_sprintf (char * s, char * fmt, ...); + +void tfp_format (void * putp, void (*putf) (void *, char), char * fmt, va_list va); + +#define printf tfp_printf +#define sprintf tfp_sprintf + +#endif diff --git a/bulb/include/common/screen.h b/bulb/include/common/screen.h new file mode 100644 index 0000000..3e969d7 --- /dev/null +++ b/bulb/include/common/screen.h @@ -0,0 +1,20 @@ +#ifndef _ROSE_C_SCREEN_H +#define _ROSE_C_SCREEN_H +#include "common/gpu.h" + +typedef struct { + unsigned int x, y; +} point_t; + +// point_t point (unsigned int x, unsigned int y); +#define POINT(x, y) \ + (point_t) { \ + x, y \ + } + +void drawpx (point_t p, color_t color); + +short get_max_width (); +short get_max_height (); + +#endif//_ROSE_C_SCREEN_H diff --git a/bulb/include/common/status_led.h b/bulb/include/common/status_led.h new file mode 100644 index 0000000..0a7096e --- /dev/null +++ b/bulb/include/common/status_led.h @@ -0,0 +1,24 @@ +#ifndef _ROSE_C_STATUS_LED_H +#define _ROSE_C_STATUS_LED_H + +#include "common/stdbool.h" +#include "kernel/mailbox.h" + +// Following https://github.com/mathlizee/Rasperry-Pi-3 + +enum { + STATUS_LED = 42, + POWER_LED = 130 +}; + +static volatile unsigned int __attribute__ ((aligned (16))) led_msg_buffer[32]; + + +bool get_led (int pin); + +void set_led (bool status, int pin); + +bool toggle_led (int pin); + + +#endif//_ROSE_C_STATUS_LED_H diff --git a/bulb/include/common/stdbool.h b/bulb/include/common/stdbool.h new file mode 100644 index 0000000..2c03282 --- /dev/null +++ b/bulb/include/common/stdbool.h @@ -0,0 +1,10 @@ +#ifndef _ROSE_C_BOOL_H +#define _ROSE_C_BOOL_H + +#define true 1 +#define false 0 +#define __bool_true_false_are_defined + +typedef char bool; + +#endif /*_ROSE_C_BOOL_H*/ diff --git a/bulb/include/common/stddef.h b/bulb/include/common/stddef.h new file mode 100644 index 0000000..8d9feaa --- /dev/null +++ b/bulb/include/common/stddef.h @@ -0,0 +1,10 @@ +#ifndef _ROSE_C_STDDEF_H +#define _ROSE_C_STDDEF_H + +#define NULL 0 + +#define ptr_t unsigned long + +#define byte_t unsigned char + +#endif//_ROSE_C_STDDEF_H \ No newline at end of file diff --git a/bulb/include/common/utils.h b/bulb/include/common/utils.h new file mode 100644 index 0000000..29b53a1 --- /dev/null +++ b/bulb/include/common/utils.h @@ -0,0 +1,12 @@ +#ifndef _ROSE_C_BOOT_H +#define _ROSE_C_BOOT_H + +extern void delay (unsigned long); + +extern void put32 (unsigned long, unsigned int); + +extern unsigned int get32 (unsigned long); + +extern int get_el (void); + +#endif /*_ROSE_C_BOOT_H */ diff --git a/bulb/include/kernel/arm/sysregs.h b/bulb/include/kernel/arm/sysregs.h new file mode 100644 index 0000000..98acd8b --- /dev/null +++ b/bulb/include/kernel/arm/sysregs.h @@ -0,0 +1,49 @@ +#ifndef _ROSE_K_A_SYSREGS_H +#define _ROSE_K_A_SYSREGS_H + +// *************************************** +// SCTLR_EL1, System Control Register (EL1), 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) + +// *************************************** +// HCR_EL2, Hypervisor Configuration Register (EL2), Page 2487 of AArch64-Reference-Manual. +// *************************************** + +#define HCR_RW (1 << 31) +#define HCR_VALUE HCR_RW + +// *************************************** +// SCR_EL3, Secure Configuration Register (EL3), 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) + +// *************************************** +// SPSR_EL3, Saved Program Status Register (EL3) 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) + +// *************************************** +// ESR_EL1, Exception Syndrome Register (EL1). Page 2431 of AArch64-Reference-Manual. +// *************************************** + +#define ESR_ELx_EC_SHIFT 26 +#define ESR_ELx_EC_SVC64 0x15 + +#endif /*_ROSE_K_A_SYSREGS_H*/ diff --git a/bulb/include/kernel/entry.h b/bulb/include/kernel/entry.h new file mode 100644 index 0000000..0152f82 --- /dev/null +++ b/bulb/include/kernel/entry.h @@ -0,0 +1,35 @@ +#ifndef _ROSE_K_ENTRY_H +#define _ROSE_K_ENTRY_H + +#define S_FRAME_SIZE 272// size of all saved registers +#define S_X0 0 // offset of x0 register in saved stack frame + +#define SYNC_INVALID_EL1t 0 +#define IRQ_INVALID_EL1t 1 +#define FIQ_INVALID_EL1t 2 +#define ERROR_INVALID_EL1t 3 + +#define SYNC_INVALID_EL1h 4 +#define IRQ_INVALID_EL1h 5 +#define FIQ_INVALID_EL1h 6 +#define ERROR_INVALID_EL1h 7 + +#define SYNC_INVALID_EL0_64 8 +#define IRQ_INVALID_EL0_64 9 +#define FIQ_INVALID_EL0_64 10 +#define ERROR_INVALID_EL0_64 11 + +#define SYNC_INVALID_EL0_32 12 +#define IRQ_INVALID_EL0_32 13 +#define FIQ_INVALID_EL0_32 14 +#define ERROR_INVALID_EL0_32 15 + +#define SYNC_ERROR 16 +#define SYSCALL_ERROR 17 + +#ifndef __ASSEMBLER__ + +void ret_from_fork (void); + +#endif +#endif diff --git a/bulb/include/kernel/mailbox.h b/bulb/include/kernel/mailbox.h new file mode 100644 index 0000000..b4f6dd8 --- /dev/null +++ b/bulb/include/kernel/mailbox.h @@ -0,0 +1,40 @@ +#ifndef _ROSE_K_MAILBOX_H +#define _ROSE_K_MAILBOX_H + +#include "common/stdbool.h" +#include "common/stddef.h" +#include "common/utils.h" +#include "kernel/mm.h" +#include "kernel/peripherals/mailbox.h" + +#include "common/debug.h" +#include "common/logging.h" + +#define DUMP_BUFFER false + +// Documentation: +// https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface + +typedef enum { + POWER = 0, + FRAMEBUFFER, + VIRTUAL_UART, + VCHIQ, + LEDS, + BUTTONS, + TOUCH_SCREEN, + RESERVED, + PROPERTY_ARM_VC,// Request from ARM for response by VC + PROPERTY_VC_ARM // Request from VC for response by ARM (Currently not in use) +} channel_t; + + +typedef struct { + unsigned int data : 28;// most significant bits contain shared memory address + channel_t channel : 4; // least four significant bits contain channel +} mbox_message_t; + +// Send message and check responses +bool mailbox_request (volatile unsigned int * data_ptr, channel_t channel); + +#endif//_ROSE_K_MAILBOX_H diff --git a/bulb/include/kernel/mm.h b/bulb/include/kernel/mm.h new file mode 100644 index 0000000..7acc222 --- /dev/null +++ b/bulb/include/kernel/mm.h @@ -0,0 +1,33 @@ +#ifndef _ROSE_K_MM_H +#define _ROSE_K_MM_H + +#include "common/stddef.h" +#include "peripherals/base.h" + +#define PAGE_SHIFT 12 +#define TABLE_SHIFT 9 +#define SECTION_SHIFT (PAGE_SHIFT + TABLE_SHIFT) + +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define SECTION_SIZE (1 << SECTION_SHIFT) + +#define LOW_MEMORY (2 * SECTION_SIZE) +#define HIGH_MEMORY 0x70000000 + +#define PAGING_MEMORY (HIGH_MEMORY - LOW_MEMORY) +#define PAGING_PAGES (PAGING_MEMORY / PAGE_SIZE) + +#ifndef __ASSEMBLER__ + +extern char _start; +#define KERNEL_START ((ptr_t) &_start) + +ptr_t get_free_page (); + +void free_page (ptr_t p); + +void memzero (ptr_t src, ptr_t n); + +#endif + +#endif /*_ROSE_K_MM_H */ diff --git a/bulb/include/kernel/mmu.h b/bulb/include/kernel/mmu.h new file mode 100644 index 0000000..3db2fbe --- /dev/null +++ b/bulb/include/kernel/mmu.h @@ -0,0 +1,38 @@ +#ifndef _ROSE_MMU_H +#define _ROSE_MMU_H + +// Implementation taken from +// https://github.com/bztsrc/raspi3-tutorial/blob/master/10_virtualmemory/mmu.c + +#include "common/logging.h" +#include "kernel/peripherals/base.h" + +#define PAGESIZE 4096 + +// granularity +#define PT_PAGE 0b11// 4k granule +#define PT_BLOCK 0b01// 2M granule +// accessibility +#define PT_KERNEL (0 << 6) // privileged, supervisor EL1 access only +#define PT_USER (1 << 6) // unprivileged, EL0 access allowed +#define PT_RW (0 << 7) // read-write +#define PT_RO (1 << 7) // read-only +#define PT_AF (1 << 10) // accessed flag +#define PT_NX (1UL << 54)// no execute +// shareability +#define PT_OSH (2 << 8)// outter shareable +#define PT_ISH (3 << 8)// inner shareable +// defined in MAIR register +#define PT_MEM (0 << 2)// normal memory +#define PT_DEV (1 << 2)// device MMIO +#define PT_NC (2 << 2)// non-cachable + +#define TTBR_CNP 1 + +// get addresses from linker +extern volatile unsigned char _data; +extern volatile unsigned char _end; + +void init_mmu (void); + +#endif//_ROSE_MMU_H \ No newline at end of file diff --git a/bulb/include/kernel/peripherals/base.h b/bulb/include/kernel/peripherals/base.h new file mode 100644 index 0000000..12f55d7 --- /dev/null +++ b/bulb/include/kernel/peripherals/base.h @@ -0,0 +1,6 @@ +#ifndef _ROSE_K_P_BASE_H +#define _ROSE_K_P_BASE_H + +#define PBASE 0xFE000000 + +#endif /*_ROSE_K_P_BASE_H */ diff --git a/bulb/include/kernel/peripherals/gpio.h b/bulb/include/kernel/peripherals/gpio.h new file mode 100644 index 0000000..8354caf --- /dev/null +++ b/bulb/include/kernel/peripherals/gpio.h @@ -0,0 +1,12 @@ +#ifndef _ROSE_K_P_GPIO_H +#define _ROSE_K_P_GPIO_H + +#include "kernel/peripherals/base.h" + +#define GPFSEL1 (PBASE + 0x00200004) +#define GPSET0 (PBASE + 0x0020001C) +#define GPCLR0 (PBASE + 0x00200028) +#define GPPUD (PBASE + 0x00200094) +#define GPPUDCLK0 (PBASE + 0x00200098) + +#endif /*_ROSE_K_P_GPIO_H */ diff --git a/bulb/include/kernel/peripherals/gpu.h b/bulb/include/kernel/peripherals/gpu.h new file mode 100644 index 0000000..2408fba --- /dev/null +++ b/bulb/include/kernel/peripherals/gpu.h @@ -0,0 +1,10 @@ +#ifndef _ROSE_K_P_GPU_H +#define _ROSE_K_P_GPU_H + +#define GPU_REQUEST_FRAMEBUFFER 0x40001 +#define GPU_BLANK_SCREEN 0x40002 +#define GPU_SET_SCREEN_SIZE 0x48003 +#define GPU_SET_VIRTUAL_SIZE 0x48004 +#define GPU_SET_COLOUR_DEPTH 0x48005 + +#endif//_ROSE_K_P_GPU_H \ No newline at end of file diff --git a/bulb/include/kernel/peripherals/mailbox.h b/bulb/include/kernel/peripherals/mailbox.h new file mode 100644 index 0000000..37f664c --- /dev/null +++ b/bulb/include/kernel/peripherals/mailbox.h @@ -0,0 +1,19 @@ +#ifndef _ROSE_K_P_MAILBOX_H +#define _ROSE_K_P_MAILBOX_H + +#include "base.h" + +#define MBOX0 (PBASE + 0xB880)// Read from CPU +#define MBOX1 (PBASE + 0xB840)// Write to CPU + +#define MBOX_READ 0x00 +#define MBOX_STATUS 0x18 +#define MBOX_IRQ 0x1C +#define MBOX_WRITE 0x20 + +#define MBOX_READ_EMPTY (1 << 30) +#define MBOX_WRITE_FULL (1 << 31) + +#define MBOX_SUCCESS 0x80000000 + +#endif//_ROSE_K_P_MAILBOX_H \ No newline at end of file diff --git a/bulb/src/common/debug.c b/bulb/src/common/debug.c new file mode 100644 index 0000000..4a65209 --- /dev/null +++ b/bulb/src/common/debug.c @@ -0,0 +1,29 @@ +#include "common/debug.h" + +void print_hex (unsigned char dec) { + char fst = dec / 16; + char snd = dec % 16; + fst = (fst > 9) ? 'A' + fst - 10 : '0' + fst; + snd = (snd > 9) ? 'A' + snd - 10 : '0' + snd; + printf ("%c%c ", fst, snd); +} + +void hex_dump (byte_t * array) { + for (int i = 0; i < *(unsigned int *) array;) { + i += 4; + for (int j = 1; j <= 4; j++) { + print_hex (array[i - j]); + } + printf (" "); + if (!(i % 32)) + printf ("\r\n"); + } + printf ("\r\n"); +} + +void int_dump (unsigned int * array) { + for (int i = 0; i < *array / 4; i++) { + printf ("%d ", array[i]); + } + printf ("\r\n"); +} diff --git a/bulb/src/common/font.c b/bulb/src/common/font.c new file mode 100644 index 0000000..ca66890 --- /dev/null +++ b/bulb/src/common/font.c @@ -0,0 +1,195 @@ +#include "common/font.h" + +/* From https://github.com/dhepper/font8x8/blob/master/font8x8_block.h */ +const unsigned long long int * font (int c) { + static const char f[128][FONT_SIZE] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0000 (nul) + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0001 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0002 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0003 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0004 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0005 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0006 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0007 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0008 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0009 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+000A + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+000B + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+000C + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+000D + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+000E + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+000F + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0010 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0011 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0012 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0013 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0014 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0015 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0016 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0017 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0018 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0019 + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+001A + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+001B + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+001C + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+001D + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+001E + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+001F + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0020 (space) + {0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00},// U+0021 (!) + {0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0022 (") + {0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00},// U+0023 (#) + {0x0C, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x0C, 0x00},// U+0024 ($) + {0x00, 0x63, 0x33, 0x18, 0x0C, 0x66, 0x63, 0x00},// U+0025 (%) + {0x1C, 0x36, 0x1C, 0x6E, 0x3B, 0x33, 0x6E, 0x00},// U+0026 (&) + {0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0027 (') + {0x18, 0x0C, 0x06, 0x06, 0x06, 0x0C, 0x18, 0x00},// U+0028 (() + {0x06, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x06, 0x00},// U+0029 ()) + {0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00},// U+002A (*) + {0x00, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x00, 0x00},// U+002B (+) + {0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x06},// U+002C (,) + {0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00},// U+002D (-) + {0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00},// U+002E (.) + {0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00},// U+002F (/) + {0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00},// U+0030 (0) + {0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00},// U+0031 (1) + {0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00},// U+0032 (2) + {0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00},// U+0033 (3) + {0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00},// U+0034 (4) + {0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00},// U+0035 (5) + {0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00},// U+0036 (6) + {0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00},// U+0037 (7) + {0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00},// U+0038 (8) + {0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00},// U+0039 (9) + {0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x00},// U+003A (:) + {0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x06},// U+003B (//) + {0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x00},// U+003C (<) + {0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x00},// U+003D (=) + {0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00},// U+003E (>) + {0x1E, 0x33, 0x30, 0x18, 0x0C, 0x00, 0x0C, 0x00},// U+003F (?) + {0x3E, 0x63, 0x7B, 0x7B, 0x7B, 0x03, 0x1E, 0x00},// U+0040 (@) + {0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00},// U+0041 (A) + {0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00},// U+0042 (B) + {0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00},// U+0043 (C) + {0x1F, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00},// U+0044 (D) + {0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00},// U+0045 (E) + {0x7F, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x0F, 0x00},// U+0046 (F) + {0x3C, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7C, 0x00},// U+0047 (G) + {0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00},// U+0048 (H) + {0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00},// U+0049 (I) + {0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, 0x00},// U+004A (J) + {0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00},// U+004B (K) + {0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00},// U+004C (L) + {0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00},// U+004D (M) + {0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00},// U+004E (N) + {0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00},// U+004F (O) + {0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00},// U+0050 (P) + {0x1E, 0x33, 0x33, 0x33, 0x3B, 0x1E, 0x38, 0x00},// U+0051 (Q) + {0x3F, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x67, 0x00},// U+0052 (R) + {0x1E, 0x33, 0x07, 0x0E, 0x38, 0x33, 0x1E, 0x00},// U+0053 (S) + {0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00},// U+0054 (T) + {0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x00},// U+0055 (U) + {0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00},// U+0056 (V) + {0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00},// U+0057 (W) + {0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00},// U+0058 (X) + {0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00},// U+0059 (Y) + {0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00},// U+005A (Z) + {0x1E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1E, 0x00},// U+005B ([) + {0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00},// U+005C (\) + {0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x00},// U+005D (]) + {0x08, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00},// U+005E (^) + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF},// U+005F (_) + {0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0060 (`) + {0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x6E, 0x00},// U+0061 (a) + {0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3B, 0x00},// U+0062 (b) + {0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00},// U+0063 (c) + {0x38, 0x30, 0x30, 0x3e, 0x33, 0x33, 0x6E, 0x00},// U+0064 (d) + {0x00, 0x00, 0x1E, 0x33, 0x3f, 0x03, 0x1E, 0x00},// U+0065 (e) + {0x1C, 0x36, 0x06, 0x0f, 0x06, 0x06, 0x0F, 0x00},// U+0066 (f) + {0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x1F},// U+0067 (g) + {0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x67, 0x00},// U+0068 (h) + {0x0C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00},// U+0069 (i) + {0x30, 0x00, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E},// U+006A (j) + {0x07, 0x06, 0x66, 0x36, 0x1E, 0x36, 0x67, 0x00},// U+006B (k) + {0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00},// U+006C (l) + {0x00, 0x00, 0x33, 0x7F, 0x7F, 0x6B, 0x63, 0x00},// U+006D (m) + {0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x00},// U+006E (n) + {0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00},// U+006F (o) + {0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F},// U+0070 (p) + {0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78},// U+0071 (q) + {0x00, 0x00, 0x3B, 0x6E, 0x66, 0x06, 0x0F, 0x00},// U+0072 (r) + {0x00, 0x00, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x00},// U+0073 (s) + {0x08, 0x0C, 0x3E, 0x0C, 0x0C, 0x2C, 0x18, 0x00},// U+0074 (t) + {0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00},// U+0075 (u) + {0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00},// U+0076 (v) + {0x00, 0x00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0x00},// U+0077 (w) + {0x00, 0x00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x00},// U+0078 (x) + {0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x1F},// U+0079 (y) + {0x00, 0x00, 0x3F, 0x19, 0x0C, 0x26, 0x3F, 0x00},// U+007A (z) + {0x38, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, 0x38, 0x00},// U+007B ({) + {0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00},// U+007C (|) + {0x07, 0x0C, 0x0C, 0x38, 0x0C, 0x0C, 0x07, 0x00},// U+007D (}) + {0x6E, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+007E (~) + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // U+007F + }; + return (unsigned long long int *) f[c]; +} + +void printc_location (point_t point, char c) { + unsigned char const * bitmap = (unsigned char const *) font (c); + for (int i = 0; i < FONT_SIZE; i++) { + for (int j = 0; j < FONT_SIZE; j++) { + bool is_on = bitmap[i] & (1 << j); + + point_t _point; + for (int k = 0; k < FONT_FACTOR; k++) { + for (int h = 0; h < FONT_FACTOR; h++) { + _point.x = point.x + j * FONT_FACTOR + k; + _point.y = point.y + i * FONT_FACTOR + h; + drawpx (_point, is_on ? font_fg : font_bg); + } + } + } + } +} + +void printc (char c) { + // Handle special characters, print otherwise + switch (c) { + case '\r':// Reset cursor to beginning of line + cursor.x = 0; + break; + case '\n':// Move cursor to next line + cursor.y += FONT_REAL_HEIGHT; + break; + case '\t':// Print minimum one space, then align forwards to tab grid + cursor.x += FONT_TAB_REAL_WIDTH - cursor.x % (FONT_TAB_REAL_WIDTH); + break; + default:// Print character and update cursor + // TODO dynamically deal with unprintable characters (i.e., check if bitmap is all '0') + printc_location (cursor, c); + cursor.x += FONT_REAL_WIDTH; + } + + // If next printed char overflowed screen width move cursor to beginning of next line + if (cursor.x + FONT_REAL_WIDTH >= get_max_width ()) { + cursor.x = 0; + cursor.y += FONT_REAL_HEIGHT; + } + // If next line would overflow screen height (ignoring line spacing) move to beginning of screen + if (cursor.y + FONT_REAL_WIDTH - FONT_SPACING >= get_max_height ()) { + // TODO clear framebuffer here...? + cursor.y = 0; + } +} + +void font_set_normal (void) { + font_fg = font_normal_fg; +} +void font_set_error (void) { + font_fg = font_error_fg; +} + +void putc_screen (void * p, char c) { + printc (c); +} diff --git a/bulb/src/common/gpu.c b/bulb/src/common/gpu.c new file mode 100644 index 0000000..4b376da --- /dev/null +++ b/bulb/src/common/gpu.c @@ -0,0 +1,137 @@ +#include "common/gpu.h" + +bool init_gpu () { + { // First message: read physical dimensions + int c = 0;// Message size; increment while we write + gpu_msg_buffer[++c] = 0;// Response - will be 0x80000000 for SUCCESS or 0x80000001 for FAILURE + + gpu_msg_buffer[++c] = 0x00040003;// Tag to get physical display width / height + gpu_msg_buffer[++c] = 8; // Size of value buffer + gpu_msg_buffer[++c] = 0; // Response & value buffer size written will be written here + gpu_msg_buffer[++c] = 0; // Get physical screen width | Overwritten by actual width + gpu_msg_buffer[++c] = 0; // Get physical screen height | Overwritten by actual height + gpu_msg_buffer[++c] = 0; // End tag + + gpu_msg_buffer[0] = (4 * ++c);// Write message size at the beginning of the buffer + + // If reading physical screen dimension fails exit function + if (! mailbox_request (gpu_msg_buffer, PROPERTY_ARM_VC)) + return false; + } + { // Second message: request frame buffer + int c = 0;// Message size; increment while we write + gpu_msg_buffer[++c] = 0;// Response - will be 0x80000000 for SUCCESS or 0x80000001 for FAILURE + +#ifdef GPU_OVERRIDE_PHYSICAL_SCREEN // If this is set, update physical /virtual dimensions based on constants + gpu_msg_buffer[++c] = 0x00048003; // Tag to set virtual display width / height + gpu_msg_buffer[++c] = 8; // Size of value buffer + gpu_msg_buffer[++c] = 0; // Response & value buffer size written will be written here + gpu_msg_buffer[++c] = GPU_SCREEN_WIDTH;// Set virtual screen width | Overwritten by actual virtual width + int index_gpu_width = c; + gpu_msg_buffer[++c] = GPU_SCREEN_HEIGHT;// Set virtual screen height | Overwritten by actual virtual height + int index_gpu_height = c; + + gpu_msg_buffer[++c] = 0x00048004; // Tag to set virtual display width / height + gpu_msg_buffer[++c] = 8; // Size of value buffer + gpu_msg_buffer[++c] = 0; // Response & value buffer size written will be written here + gpu_msg_buffer[++c] = GPU_VIRTUAL_WIDTH;// Set virtual screen width | Overwritten by actual virtual width + int index_width = c; + gpu_msg_buffer[++c] = GPU_VIRTUAL_HEIGHT;// Set virtual screen height | Overwritten by actual virtual height + int index_height = c; +#else + gpu_msg_buffer[++c] = 0x00048004;// Tag to set virtual display width / height + gpu_msg_buffer[++c] = 8; // Size of value buffer + gpu_msg_buffer[++c] = 0; // Response & value buffer size written will be written here + gpu_msg_buffer[++c]; //GPU_SCREEN_WIDTH; // Reuse previous width | Overwritten by actual virtual width + int index_width = c; + gpu_msg_buffer[++c];//GPU_SCREEN_HEIGHT; // Reuse previous height | Overwritten by actual virtual height + int index_height = c; +#endif + + gpu_msg_buffer[++c] = 0x00048005; // Tag to set pixel depth + gpu_msg_buffer[++c] = 4; // Size of value buffer + gpu_msg_buffer[++c] = 0; // Response & value buffer size written will be written here + gpu_msg_buffer[++c] = GPU_COLOUR_DEPTH;// Set colour depth | Overwritten by actual colour depth + + gpu_msg_buffer[++c] = 0x00040001;// Tag to allocate framebuffer + gpu_msg_buffer[++c] = 8; // Size of value buffer + gpu_msg_buffer[++c] = 0; // Response & value buffer size will be written here + gpu_msg_buffer[++c] = 16; // Buffer alignment | Overwritten by pointer to framebuffer + int index_framebuffer = c; + gpu_msg_buffer[++c] = 0;// Unused - will be overwritten | Overwritten by size of framebuffer + int index_fb_size = c; + + gpu_msg_buffer[++c] = 0;// End tag + gpu_msg_buffer[++c] = 0;// Padding + gpu_msg_buffer[++c] = 0;// Padding + gpu_msg_buffer[++c] = 0;// Padding + + gpu_msg_buffer[0] = (4 * ++c);// Write message size at the beginning of the buffer + + // If message failed exit + if (! mailbox_request (gpu_msg_buffer, PROPERTY_ARM_VC)) + return false; + + // Since message succeeded, update frame buffer and its size + fb_info.fb = (color_t *) (long) (gpu_msg_buffer[index_framebuffer] & VC_SDRAM_OFFSET); + fb_info.fb_size = gpu_msg_buffer[index_fb_size]; + + // printf ("PHY_WIDTH: %d, PHY_HEIGHT: %d, VIRT_WIDTH: %d, VIRT_HEIGHT: %d\n\r", gpu_msg_buffer[index_gpu_width], gpu_msg_buffer[index_gpu_height], gpu_msg_buffer[index_width], gpu_msg_buffer[index_height]); + + fb_info.virtual_width = gpu_msg_buffer[index_width]; + fb_info.virtual_height = gpu_msg_buffer[index_height]; + } + { // Third message: read pitch (in bytes per line) + int c = 0;// Message size; increment while we write + gpu_msg_buffer[++c] = 0;// Response - will be 0x80000000 for SUCCESS or 0x80000001 for FAILURE + + gpu_msg_buffer[++c] = 0x00040008;// Tag to get pitch + gpu_msg_buffer[++c] = 4; // Size of value buffer + gpu_msg_buffer[++c] = 0; // Response & value buffer size written will be written here + gpu_msg_buffer[++c] = 0; // Pitch will be written here + int index_pitch = c; + + gpu_msg_buffer[++c] = 0;// End tag + gpu_msg_buffer[++c] = 0;// Padding + + gpu_msg_buffer[0] = (4 * ++c);// Write message size at the beginning of the buffer + + // If message failed exit + if (! mailbox_request (gpu_msg_buffer, PROPERTY_ARM_VC)) + return false; + + // Else write pitch appropriately + fb_info.pitch = gpu_msg_buffer[index_pitch]; + } + return true; +} + +color_t * get_fb () { + return fb_info.fb; +} + +fb_info_t const * get_fb_info () { + return &fb_info; +} + +bool blank_screen (bool blank) { + int c = 0;// Message size; increment while we write + gpu_msg_buffer[++c] = 0;// Response - will be 0x80000000 for SUCCESS or 0x80000001 for FAILURE + + gpu_msg_buffer[++c] = 0x00040002;// Tag to blank screen + gpu_msg_buffer[++c] = 4; // Size of value buffer + gpu_msg_buffer[++c] = 0; // + gpu_msg_buffer[++c] = blank; // On or off + + gpu_msg_buffer[++c] = 0;// End tag + gpu_msg_buffer[++c] = 0;// Padding + + gpu_msg_buffer[0] = (4 * ++c);// Write message size at the beginning of the buffer + + return mailbox_request (gpu_msg_buffer, PROPERTY_ARM_VC); +} + +bool toggle_blank_screen (void) { + static bool is_blank = false; + blank_screen (is_blank = ! is_blank); +} \ No newline at end of file diff --git a/bulb/src/common/printf.c b/bulb/src/common/printf.c new file mode 100644 index 0000000..059ee24 --- /dev/null +++ b/bulb/src/common/printf.c @@ -0,0 +1,243 @@ +/* +File: printf.c + +Copyright (C) 2004 Kustaa Nyholm + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "common/printf.h" + +typedef void (*putcf) (void *, char); + +static putcf stdout_putf; +static void * stdout_putp; + + +#ifdef PRINTF_LONG_SUPPORT + +static void uli2a (unsigned long int num, unsigned int base, int uc, char * bf) { + int n = 0; + unsigned int d = 1; + while (num / d >= base) + d *= base; + while (d != 0) { + int dgt = num / d; + num %= d; + d /= base; + if (n || dgt > 0 || d == 0) { + *bf++ = dgt + (dgt < 10 ? '0' : (uc ? 'A' : 'a') - 10); + ++n; + } + } + *bf = 0; +} + +static void li2a (long num, char * bf) { + if (num < 0) { + num = -num; + *bf++ = '-'; + } + uli2a (num, 10, 0, bf); +} + +#endif + +static void ui2a (unsigned int num, unsigned int base, int uc, char * bf) { + int n = 0; + unsigned int d = 1; + while (num / d >= base) + d *= base; + while (d != 0) { + int dgt = num / d; + num %= d; + d /= base; + if (n || dgt > 0 || d == 0) { + *bf++ = dgt + (dgt < 10 ? '0' : (uc ? 'A' : 'a') - 10); + ++n; + } + } + *bf = 0; +} + +static void i2a (int num, char * bf) { + if (num < 0) { + num = -num; + *bf++ = '-'; + } + ui2a (num, 10, 0, bf); +} + +static int a2d (char ch) { + if (ch >= '0' && ch <= '9') { + return ch - '0'; + } else if (ch >= 'a' && ch <= 'f') { + return ch - 'a' + 10; + } else if (ch >= 'A' && ch <= 'F') { + return ch - 'A' + 10; + } else { + return -1; + } +} + +static char a2i (char ch, char ** src, int base, int * nump) { + char * p = *src; + int num = 0; + int digit; + while ((digit = a2d (ch)) >= 0) { + if (digit > base) + break; + num = num * base + digit; + ch = *p++; + } + *src = p; + *nump = num; + return ch; +} + +static void putchw (void * putp, putcf putf, int n, char z, char * bf) { + char fc = z ? '0' : ' '; + char ch; + char * p = bf; + while (*p++ && n > 0) + n--; + while (n-- > 0) + putf (putp, fc); + while ((ch = *bf++)) + putf (putp, ch); +} + +void tfp_format (void * putp, putcf putf, char * fmt, va_list va) { + char bf[12]; + + char ch; + + + while ((ch = *(fmt++))) { + if (ch != '%') { + putf (putp, ch); + } else { + char lz = 0; +#ifdef PRINTF_LONG_SUPPORT + char lng = 0; +#endif + int w = 0; + ch = *(fmt++); + if (ch == '0') { + ch = *(fmt++); + lz = 1; + } + if (ch >= '0' && ch <= '9') { + ch = a2i (ch, &fmt, 10, &w); + } +#ifdef PRINTF_LONG_SUPPORT + if (ch == 'l') { + ch = *(fmt++); + lng = 1; + } +#endif + switch (ch) { + case 0: + goto abort; + case 'u': { +#ifdef PRINTF_LONG_SUPPORT + if (lng) + uli2a (va_arg (va, unsigned long int), 10, 0, bf); + else +#endif + ui2a (va_arg (va, + unsigned int), 10, 0, bf); + putchw (putp, putf, w, lz, bf); + break; + } + case 'd': { +#ifdef PRINTF_LONG_SUPPORT + if (lng) + li2a (va_arg (va, unsigned long int), bf); + else +#endif + i2a (va_arg (va, + int), bf); + putchw (putp, putf, w, lz, bf); + break; + } + case 'x': + case 'X': +#ifdef PRINTF_LONG_SUPPORT + if (lng) + uli2a (va_arg (va, unsigned long int), 16, (ch == 'X'), bf); + else +#endif + ui2a (va_arg (va, + unsigned int), 16, (ch == 'X'), bf); + putchw (putp, putf, w, lz, bf); + break; + case 'c' : + putf (putp, (char) (va_arg (va, + int))); + break; + case 's' : + putchw (putp, putf, w, 0, va_arg (va, + char*)); + break; + case 'p': + case 'P': + putf (putp, '0'); + putf (putp, 'x'); +#ifdef PRINTF_LONG_SUPPORT + if (lng) + uli2a (va_arg (va, unsigned long int), 16, (ch == 'P'), bf); + else +#endif + ui2a (va_arg (va, + unsigned int), 16, (ch == 'P'), bf); + putchw (putp, putf, w, lz, bf); + break; + case '%': + putf (putp, ch); + default: + break; + } + } + } +abort:; +} + + +void init_printf (void * putp, void (*putf) (void *, char)) { + stdout_putf = putf; + stdout_putp = putp; +} + +void tfp_printf (char * fmt, ...) { + va_list va; + va_start (va, fmt); + tfp_format (stdout_putp, stdout_putf, fmt, va); + va_end (va); +} + +static void putcp (void * p, char c) { + *(*((char **) p))++ = c; +} + + +void tfp_sprintf (char * s, char * fmt, ...) { + va_list va; + va_start (va, fmt); + tfp_format (&s, putcp, fmt, va); + putcp (&s, 0); + va_end (va); +} diff --git a/bulb/src/common/screen.c b/bulb/src/common/screen.c new file mode 100644 index 0000000..b09764d --- /dev/null +++ b/bulb/src/common/screen.c @@ -0,0 +1,14 @@ +#include "common/screen.h" + +void drawpx (point_t p, color_t color) { + unsigned long int location = p.y * (get_fb_info ()->pitch) / sizeof (color_t) + p.x; + get_fb ()[location] = color; +}; + +short get_max_width () { + return get_fb_info ()->virtual_width - 1; +} + +short get_max_height () { + return get_fb_info ()->virtual_height - 1; +} diff --git a/bulb/src/common/status_led.c b/bulb/src/common/status_led.c new file mode 100644 index 0000000..b8b1b03 --- /dev/null +++ b/bulb/src/common/status_led.c @@ -0,0 +1,55 @@ +#include "common/status_led.h" + +bool get_led (int pin) { + // Try to read ACT LED state + int c = 0;// Message size; increment while we write + led_msg_buffer[++c] = 0;// Response - will be 0x80000000 for SUCCESS or 0x80000001 for FAILURE + + led_msg_buffer[++c] = 0x00030041;// Tag to get ACT LED state + led_msg_buffer[++c] = 8; // Size of value buffer + led_msg_buffer[++c] = 0; // Response & value buffer size written will be written here + led_msg_buffer[++c] = pin; // + led_msg_buffer[++c] = 0; // + int index_led = c; + + led_msg_buffer[++c] = 0;// End tag + + led_msg_buffer[0] = (4 * ++c);// Write message size at the beginning of the buffer + + if (! mailbox_request (led_msg_buffer, PROPERTY_ARM_VC)) { + printf ("ERROR\r\n"); + }; + return ! led_msg_buffer[index_led]; +} + +/** + * Change LED state + * Pins: + * - Power LED: 130 (0 to turn on and 1 to turn off) + * - ACT LED: 42 (1 to turn on and 0 to turn off) +**/ +void set_led (bool status, int pin) { + // Try to read ACT LED state + int c = 0;// Message size; increment while we write + led_msg_buffer[++c] = 0;// Response - will be 0x80000000 for SUCCESS or 0x80000001 for FAILURE + + led_msg_buffer[++c] = 0x00038041;// Tag to get ACT LED state + led_msg_buffer[++c] = 8; // Size of value buffer + led_msg_buffer[++c] = 0; // Response & value buffer size written will be written here + led_msg_buffer[++c] = pin; + led_msg_buffer[++c] = status; + + led_msg_buffer[++c] = 0;// End tag + + led_msg_buffer[0] = (4 * ++c);// Write message size at the beginning of the buffer + + if (! mailbox_request (led_msg_buffer, PROPERTY_ARM_VC)) { + printf ("ERROR\r\n"); + }; +} + +bool toggle_led (int pin) { + bool status = get_led (pin); + set_led (status, pin); + return status; +} diff --git a/bulb/src/common/utils.S b/bulb/src/common/utils.S new file mode 100644 index 0000000..44be485 --- /dev/null +++ b/bulb/src/common/utils.S @@ -0,0 +1,21 @@ +.globl get_el +get_el: + mrs x0, CurrentEL + lsr x0, x0, #2 + ret + +.globl put32 +put32: + str w1,[x0] + ret + +.globl get32 +get32: + ldr w0,[x0] + ret + +.globl delay +delay: + subs x0, x0, #1 + bne delay + ret diff --git a/bulb/src/config.txt b/bulb/src/config.txt new file mode 100644 index 0000000..1cb4eed --- /dev/null +++ b/bulb/src/config.txt @@ -0,0 +1,2 @@ +enable_uart=1 +dtparam=watchdog=on diff --git a/bulb/src/kernel/boot.S b/bulb/src/kernel/boot.S new file mode 100644 index 0000000..14bc88a --- /dev/null +++ b/bulb/src/kernel/boot.S @@ -0,0 +1,52 @@ +#include "kernel/arm/sysregs.h" + +#include "kernel/mm.h" + +.section ".text.boot" + +.globl _start +_start: + mrs x0, mpidr_el1 + and x0, x0,#0xFF // Check processor id + cbz x0, init_bss // Hang for all non-primary CPU + + wfe + + b master + +init_bss: + adr x0, __bss_start + adr x1, __bss_end + sub x1, x1, x0 + bl memzero + + b move_to_el1 + +move_to_el1: + ldr x0, =SCTLR_VALUE_MMU_DISABLED + msr sctlr_el1, x0 + + ldr x0, =HCR_VALUE + msr hcr_el2, x0 + + ldr x0, =SPSR_VALUE + msr spsr_el2, x0 + + adr x0, master + msr elr_el2, x0 + + eret + +master: + mrs x0, mpidr_el1 + and x0, x0, #0xFF + mov x1, #SECTION_SIZE + mul x1, x1, x0 + add x1, x1, #LOW_MEMORY + mov sp, x1 + + bl kernel_main + +proc_hang: + b proc_hang + diff --git a/bulb/src/kernel/kernel.c b/bulb/src/kernel/kernel.c new file mode 100644 index 0000000..d4cc08b --- /dev/null +++ b/bulb/src/kernel/kernel.c @@ -0,0 +1,43 @@ +#include "common/font.h" +#include "common/gpu.h" +#include "common/logging.h" +#include "common/printf.h" +#include "common/status_led.h" +#include "common/utils.h" +#include "kernel/mm.h" +#include "kernel/mmu.h" + +void hang (int led, int cycles) { + while (1) { + toggle_led (led); + delay (cycles); + } +} + +void kernel_init (void) { + set_led (0, POWER_LED); + set_led (0, STATUS_LED); + + if (init_gpu ()) { + if (get_fb ()) { + font_set_normal (); + init_printf (0, putc_screen); + printf ("Frame buffer: %p\r\n", get_fb ()); + printf ("Width resolution: %d\r\n", get_fb_info ()->virtual_width); + printf ("Height resolution: %d\r\n", get_fb_info ()->virtual_height); + + LOG ("Initialisation done"); + ERROR ("I'm important!"); + } else + hang (POWER_LED, 1000000); + } else + hang (POWER_LED, 2000000); +} + +void kernel_main (int processor_id) { + kernel_init (); + + printf ("Hello, from processor %d in EL %d\r\n", processor_id, get_el ()); + + hang (STATUS_LED, 5000000); +} diff --git a/bulb/src/kernel/mailbox.c b/bulb/src/kernel/mailbox.c new file mode 100644 index 0000000..a744c50 --- /dev/null +++ b/bulb/src/kernel/mailbox.c @@ -0,0 +1,52 @@ +#include "kernel/mailbox.h" + +bool mailbox_request (volatile unsigned int * data_ptr, channel_t channel) { + volatile unsigned int * buffer = data_ptr; + + if (DUMP_BUFFER) { + LOG ("Dumping message buffer before sending:"); + int_dump ((unsigned int *) buffer); + hex_dump ((byte_t *) buffer); + } + + // 28-bit address (MSB) and 4-bit value (LSB) + unsigned int outgoing = ((unsigned int) ((long) data_ptr) & ~0xF) | (channel & 0xF); + + // Wait until we can write + while (get32 (MBOX0 + MBOX_STATUS) & MBOX_WRITE_FULL) + ; + + // Write the address of our buffer to the mailbox with the channel appended + put32 (MBOX0 + MBOX_WRITE, outgoing); + + unsigned int incoming; + while (1) { + // Is there a reply? + while (get32 (MBOX0 + MBOX_STATUS) & MBOX_READ_EMPTY) + ; + + incoming = get32 (MBOX0 + MBOX_READ); + + // Is it a reply to our message? + if (outgoing == incoming) { + if (buffer[1] != MBOX_SUCCESS) { + if (DUMP_BUFFER) { + LOG ("Dumping failed message buffer:"); + int_dump ((unsigned int *) buffer); + hex_dump ((byte_t *) buffer); + } + + return false; + } + break; + } + } + + if (DUMP_BUFFER) { + LOG ("Dumping successful message buffer:"); + int_dump ((unsigned int *) buffer); + hex_dump ((byte_t *) buffer); + } + + return true; +} diff --git a/bulb/src/kernel/mm.S b/bulb/src/kernel/mm.S new file mode 100644 index 0000000..92e5692 --- /dev/null +++ b/bulb/src/kernel/mm.S @@ -0,0 +1,14 @@ +.globl memcpy +memcpy: + ldr x3, [x1], #8 + str x3, [x0], #8 + subs x2, x2, #8 + b.gt memcpy + ret + +.globl memzero +memzero: + str xzr, [x0], #8 + subs x1, x1, #8 + b.gt memzero + ret diff --git a/bulb/src/kernel/mm.c b/bulb/src/kernel/mm.c new file mode 100644 index 0000000..f4da23c --- /dev/null +++ b/bulb/src/kernel/mm.c @@ -0,0 +1,19 @@ +#include "kernel/mm.h" + +static unsigned short mem_map[PAGING_PAGES] = { + 0, +}; + +ptr_t get_free_page () { + for (int i = 0; i < PAGING_PAGES; i++) { + if (mem_map[i] == 0) { + mem_map[i] = 1; + return LOW_MEMORY + i * PAGE_SIZE; + } + } + return 0; +} + +void free_page (ptr_t p) { + mem_map[(p - LOW_MEMORY) / PAGE_SIZE] = 0; +} diff --git a/bulb/src/kernel/mmu.c b/bulb/src/kernel/mmu.c new file mode 100644 index 0000000..f675d98 --- /dev/null +++ b/bulb/src/kernel/mmu.c @@ -0,0 +1,134 @@ +#include "kernel/mmu.h" + +void init_mmu () { + unsigned long data_page = (unsigned long) &_data / PAGESIZE; + unsigned long r, b, *paging = (unsigned long *) &_end; + + /* create MMU translation tables at _end */ + + // TTBR0, identity L1 + paging[0] = (unsigned long) ((unsigned char *) &_end + 2 * PAGESIZE) |// physical address + PT_PAGE | // it has the "Present" flag, which must be set, and we have area in it mapped by pages + PT_AF | // accessed flag. Without this we're going to have a Data Abort exception + PT_USER | // non-privileged + PT_ISH | // inner shareable + PT_MEM; // normal memory + + // identity L2, first 2M block + paging[2 * 512] = (unsigned long) ((unsigned char *) &_end + 3 * PAGESIZE) |// physical address + PT_PAGE | // we have area in it mapped by pages + PT_AF | // accessed flag + PT_USER | // non-privileged + PT_ISH | // inner shareable + PT_MEM; // normal memory + + // identity L2 2M blocks + b = PBASE >> 21; + // skip 0th, as we're about to map it by L3 + for (r = 1; r < 512; r++) + paging[2 * 512 + r] = (unsigned long) ((r << 21)) | // physical address + PT_BLOCK | // map 2M block + PT_AF | // accessed flag + PT_NX | // no execute + PT_USER | // non-privileged + (r >= b ? PT_OSH | PT_DEV : PT_ISH | PT_MEM);// different attributes for device memory + + // identity L3 + for (r = 0; r < 512; r++) + paging[3 * 512 + r] = (unsigned long) (r * PAGESIZE) | // physical address + PT_PAGE | // map 4k + PT_AF | // accessed flag + PT_USER | // non-privileged + PT_ISH | // inner shareable + ((r < 0x80 || r >= data_page) ? PT_RW | PT_NX : PT_RO);// different for code and data + + // TTBR1, kernel L1 + paging[512 + 511] = (unsigned long) ((unsigned char *) &_end + 4 * PAGESIZE) |// physical address + PT_PAGE | // we have area in it mapped by pages + PT_AF | // accessed flag + PT_KERNEL | // privileged + PT_ISH | // inner shareable + PT_MEM; // normal memory + + // kernel L2 + paging[4 * 512 + 511] = (unsigned long) ((unsigned char *) &_end + 5 * PAGESIZE) |// physical address + PT_PAGE | // we have area in it mapped by pages + PT_AF | // accessed flag + PT_KERNEL | // privileged + PT_ISH | // inner shareable + PT_MEM; // normal memory + + // kernel L3 + paging[5 * 512] = (unsigned long) (PBASE + 0x00201000) |// physical address + PT_PAGE | // map 4k + PT_AF | // accessed flag + PT_NX | // no execute + PT_KERNEL | // privileged + PT_OSH | // outter shareable + PT_DEV; // device memory + + /* okay, now we have to set system registers to enable MMU */ + + // check for 4k granule and at least 36 bits physical address bus */ + asm volatile("mrs %0, id_aa64mmfr0_el1" + : "=r"(r)); + b = r & 0xF; + if (r & (0xF << 28) /*4k*/ || b < 1 /*36 bits*/) { + ERROR ("ERROR: 4k granule or 36 bit address space not supported\n"); + return; + } + + // first, set Memory Attributes array, indexed by PT_MEM, PT_DEV, PT_NC in our example + r = (0xFF << 0) |// AttrIdx=0: normal, IWBWA, OWBWA, NTR + (0x04 << 8) |// AttrIdx=1: device, nGnRE (must be OSH too) + (0x44 << 16);// AttrIdx=2: non cacheable + asm volatile("msr mair_el1, %0" + : + : "r"(r)); + + // next, specify mapping characteristics in translate control register + r = (0b00LL << 37) |// TBI=0, no tagging + (b << 32) | // IPS=autodetected + (0b10LL << 30) |// TG1=4k + (0b11LL << 28) |// SH1=3 inner + (0b01LL << 26) |// ORGN1=1 write back + (0b01LL << 24) |// IRGN1=1 write back + (0b0LL << 23) | // EPD1 enable higher half + (25LL << 16) | // T1SZ=25, 3 levels (512G) + (0b00LL << 14) |// TG0=4k + (0b11LL << 12) |// SH0=3 inner + (0b01LL << 10) |// ORGN0=1 write back + (0b01LL << 8) | // IRGN0=1 write back + (0b0LL << 7) | // EPD0 enable lower half + (25LL << 0); // T0SZ=25, 3 levels (512G) + asm volatile("msr tcr_el1, %0; isb" + : + : "r"(r)); + + // tell the MMU where our translation tables are. TTBR_CNP bit not documented, but required + // lower half, user space + asm volatile("msr ttbr0_el1, %0" + : + : "r"((unsigned long) &_end + TTBR_CNP)); + // upper half, kernel space + asm volatile("msr ttbr1_el1, %0" + : + : "r"((unsigned long) &_end + TTBR_CNP + PAGESIZE)); + + // finally, toggle some bits in system control register to enable page translation + asm volatile("dsb ish; isb; mrs %0, sctlr_el1" + : "=r"(r)); + r |= 0xC00800; // set mandatory reserved bits + r &= ~((1 << 25) |// clear EE, little endian translation tables + (1 << 24) |// clear E0E + (1 << 19) |// clear WXN + (1 << 12) |// clear I, no instruction cache + (1 << 4) | // clear SA0 + (1 << 3) | // clear SA + (1 << 2) | // clear C, no cache at all + (1 << 1)); // clear A, no aligment check + r |= (1 << 0); // set M, enable MMU + asm volatile("msr sctlr_el1, %0; isb" + : + : "r"(r)); +} \ No newline at end of file diff --git a/bulb/src/linker.ld b/bulb/src/linker.ld new file mode 100644 index 0000000..332bfc8 --- /dev/null +++ b/bulb/src/linker.ld @@ -0,0 +1,19 @@ +SECTIONS +{ + . = 0x80000; + .text.boot : { *(.text.boot) } + .text : { *(.text) } + .rodata : { *(.rodata) } + PROVIDE(_data = .); + .data : { *(.data) } + .bss (NOLOAD) : { + . = ALIGN(16); + __bss_start = .; + *(.bss .bss.*) + *(COMMON) + __bss_end = .; + } + . = ALIGN(4096); + _end = .; +} +__bss_size = (__bss_end - __bss_start) >> 3; \ No newline at end of file From 8efba797d1815567ef22c9f7c860daf3a1ba129b Mon Sep 17 00:00:00 2001 From: Aaron Alef Date: Tue, 2 Nov 2021 13:02:13 +0100 Subject: [PATCH 02/21] chore(mmu): add logging to mmu init --- bulb/include/kernel/mmu.h | 1 + bulb/src/kernel/kernel.c | 2 ++ bulb/src/kernel/mmu.c | 13 +++++++++++++ 3 files changed, 16 insertions(+) diff --git a/bulb/include/kernel/mmu.h b/bulb/include/kernel/mmu.h index 3db2fbe..e72bea5 100644 --- a/bulb/include/kernel/mmu.h +++ b/bulb/include/kernel/mmu.h @@ -5,6 +5,7 @@ // https://github.com/bztsrc/raspi3-tutorial/blob/master/10_virtualmemory/mmu.c #include "common/logging.h" +#include "common/status_led.h" #include "kernel/peripherals/base.h" #define PAGESIZE 4096 diff --git a/bulb/src/kernel/kernel.c b/bulb/src/kernel/kernel.c index d4cc08b..ab7eac3 100644 --- a/bulb/src/kernel/kernel.c +++ b/bulb/src/kernel/kernel.c @@ -37,6 +37,8 @@ void kernel_init (void) { void kernel_main (int processor_id) { kernel_init (); + init_mmu (); + printf ("Hello, from processor %d in EL %d\r\n", processor_id, get_el ()); hang (STATUS_LED, 5000000); diff --git a/bulb/src/kernel/mmu.c b/bulb/src/kernel/mmu.c index f675d98..62fbfea 100644 --- a/bulb/src/kernel/mmu.c +++ b/bulb/src/kernel/mmu.c @@ -68,6 +68,7 @@ void init_mmu () { PT_DEV; // device memory /* okay, now we have to set system registers to enable MMU */ + // hang (POWER_LED, 2000000); // check for 4k granule and at least 36 bits physical address bus */ asm volatile("mrs %0, id_aa64mmfr0_el1" @@ -85,6 +86,7 @@ void init_mmu () { asm volatile("msr mair_el1, %0" : : "r"(r)); + LOG ("MAIR attributes written"); // next, specify mapping characteristics in translate control register r = (0b00LL << 37) |// TBI=0, no tagging @@ -105,15 +107,20 @@ void init_mmu () { : : "r"(r)); + LOG ("Translation control register written"); + // tell the MMU where our translation tables are. TTBR_CNP bit not documented, but required // lower half, user space asm volatile("msr ttbr0_el1, %0" : : "r"((unsigned long) &_end + TTBR_CNP)); + LOG ("TTBR0 written"); + // upper half, kernel space asm volatile("msr ttbr1_el1, %0" : : "r"((unsigned long) &_end + TTBR_CNP + PAGESIZE)); + LOG ("TTBR1 written"); // finally, toggle some bits in system control register to enable page translation asm volatile("dsb ish; isb; mrs %0, sctlr_el1" @@ -128,7 +135,13 @@ void init_mmu () { (1 << 2) | // clear C, no cache at all (1 << 1)); // clear A, no aligment check r |= (1 << 0); // set M, enable MMU + + LOG ("Read out system control register"); + asm volatile("msr sctlr_el1, %0; isb" : : "r"(r)); + + LOG ("Modify and write back system control register flags"); + return; } \ No newline at end of file From 20e271c38a29b4bc3fd93a7f14e71c7f0a901e61 Mon Sep 17 00:00:00 2001 From: Aaron Alef Date: Tue, 2 Nov 2021 14:01:18 +0100 Subject: [PATCH 03/21] chore(mmu): add some debugging... --- bulb/include/common/font.h | 6 ++++++ bulb/include/kernel/mmu.h | 6 ++++++ bulb/src/common/font.c | 8 ++++++++ bulb/src/kernel/mmu.c | 15 ++++++++++++--- 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/bulb/include/common/font.h b/bulb/include/common/font.h index 5b49ada..b732416 100644 --- a/bulb/include/common/font.h +++ b/bulb/include/common/font.h @@ -13,8 +13,14 @@ #define FONT_TAB_SIZE 4 #define FONT_TAB_REAL_WIDTH (FONT_TAB_SIZE * FONT_REAL_WIDTH) +// If this is defined, scrollback is used +#define FONT_SCROLLBACK +// Scroll by this amount at the same time. High = fast, low = fancy +#define FONT_SB_LINES 1 + #include "common/gpu.h" #include "common/screen.h" +#include "kernel/mm.h" static point_t cursor = {0, 0}; diff --git a/bulb/include/kernel/mmu.h b/bulb/include/kernel/mmu.h index e72bea5..471bb20 100644 --- a/bulb/include/kernel/mmu.h +++ b/bulb/include/kernel/mmu.h @@ -36,4 +36,10 @@ extern volatile unsigned char _end; void init_mmu (void); +static char msg[] = "tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt889898ttttttttttttttttttttttttttttttttttttttttttttttttt908ttttttttttttttttttttttttttttttttttttttt+-" + "tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt889898ttttttttttttttttttttttttttttttttttttttttttttttttt908ttttttttttttttttttttttttttttttttttttttt+-" + "tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt889898ttttttttttttttttttttttttttttttttttttttttttttttttt908ttttttttttttttttttttttttttttttttttttttt+-" + "tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt889898ttttttttttttttttttttttttttttttttttttttttttttttttt908ttttttttttttttttttttttttttttttttttttttt+-" + "tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt889898ttttttttttttttttttttttttttttttttttttttttttttttttt908ttttttttttttttttttttttttttttttt########+-"; + #endif//_ROSE_MMU_H \ No newline at end of file diff --git a/bulb/src/common/font.c b/bulb/src/common/font.c index ca66890..8e61da3 100644 --- a/bulb/src/common/font.c +++ b/bulb/src/common/font.c @@ -178,8 +178,16 @@ void printc (char c) { } // If next line would overflow screen height (ignoring line spacing) move to beginning of screen if (cursor.y + FONT_REAL_WIDTH - FONT_SPACING >= get_max_height ()) { +#ifndef FONT_SCROLLBACK + cursor.y -= FONT_SB_LINES * FONT_REAL_HEIGHT; + unsigned int remove_size = FONT_SB_LINES * FONT_REAL_HEIGHT * get_fb_info ()->pitch; + unsigned int scroll_size = get_fb_info ()->fb_size - remove_size; + memcpy ((ptr_t) get_fb (), (ptr_t) get_fb () + remove_size, scroll_size); + memzero ((ptr_t) get_fb () + scroll_size, remove_size); +#else // TODO clear framebuffer here...? cursor.y = 0; +#endif } } diff --git a/bulb/src/kernel/mmu.c b/bulb/src/kernel/mmu.c index 62fbfea..03a6afc 100644 --- a/bulb/src/kernel/mmu.c +++ b/bulb/src/kernel/mmu.c @@ -78,6 +78,7 @@ void init_mmu () { ERROR ("ERROR: 4k granule or 36 bit address space not supported\n"); return; } + LOG ("4k granule and 36bit address bus ensured"); // first, set Memory Attributes array, indexed by PT_MEM, PT_DEV, PT_NC in our example r = (0xFF << 0) |// AttrIdx=0: normal, IWBWA, OWBWA, NTR @@ -106,7 +107,6 @@ void init_mmu () { asm volatile("msr tcr_el1, %0; isb" : : "r"(r)); - LOG ("Translation control register written"); // tell the MMU where our translation tables are. TTBR_CNP bit not documented, but required @@ -142,6 +142,15 @@ void init_mmu () { : : "r"(r)); - LOG ("Modify and write back system control register flags"); - return; + LOG ("Set SCTLR flags and enable MMU"); + + while (1) { + printc ('.'); + } + // printf (msg); + // printf ("test"); + + set_led (POWER_LED, 1); + + hang (STATUS_LED, 2000000); } \ No newline at end of file From 48523398e9d765168c78df3c9fb2a1c530c0b76d Mon Sep 17 00:00:00 2001 From: Aaron Alef Date: Wed, 3 Nov 2021 11:51:05 +0100 Subject: [PATCH 04/21] feat(bulb): add irq to show MMU calls sync invalid exception --- bulb/include/kernel/arm/sysregs.h | 6 +- bulb/include/kernel/irq.h | 23 +++ bulb/include/kernel/mini_uart.h | 33 ++++ bulb/include/kernel/mmu.h | 10 +- bulb/include/kernel/peripherals/irq.h | 37 ++++ bulb/include/kernel/peripherals/mini_uart.h | 25 +++ bulb/src/kernel/entry.S | 181 ++++++++++++++++++++ bulb/src/kernel/irq.S | 15 ++ bulb/src/kernel/irq.c | 55 ++++++ bulb/src/kernel/kernel.c | 16 ++ bulb/src/kernel/mini_uart.c | 88 ++++++++++ bulb/src/kernel/mmu.c | 46 +++-- 12 files changed, 518 insertions(+), 17 deletions(-) create mode 100644 bulb/include/kernel/irq.h create mode 100644 bulb/include/kernel/mini_uart.h create mode 100644 bulb/include/kernel/peripherals/irq.h create mode 100644 bulb/include/kernel/peripherals/mini_uart.h create mode 100644 bulb/src/kernel/entry.S create mode 100644 bulb/src/kernel/irq.S create mode 100644 bulb/src/kernel/irq.c create mode 100644 bulb/src/kernel/mini_uart.c diff --git a/bulb/include/kernel/arm/sysregs.h b/bulb/include/kernel/arm/sysregs.h index 98acd8b..ccdda11 100644 --- a/bulb/include/kernel/arm/sysregs.h +++ b/bulb/include/kernel/arm/sysregs.h @@ -43,7 +43,9 @@ // ESR_EL1, Exception Syndrome Register (EL1). Page 2431 of AArch64-Reference-Manual. // *************************************** -#define ESR_ELx_EC_SHIFT 26 -#define ESR_ELx_EC_SVC64 0x15 +#define ESR_ELx_EC_SHIFT 26 +#define ESR_ELx_EC_SVC64 0x15 +#define ESR_ELx_EC_DABT_LOW 0b100100 +#define ESR_ELx_EC_DABT_SAME 0b100101 #endif /*_ROSE_K_A_SYSREGS_H*/ diff --git a/bulb/include/kernel/irq.h b/bulb/include/kernel/irq.h new file mode 100644 index 0000000..9221696 --- /dev/null +++ b/bulb/include/kernel/irq.h @@ -0,0 +1,23 @@ +#ifndef _ROSE_K_IRQ_H +#define _ROSE_K_IRQ_H + +#include "common/printf.h" +#include "common/stddef.h" +#include "common/utils.h" +#include "kernel/arm/sysregs.h" +#include "kernel/entry.h" +#include "kernel/peripherals/irq.h" + +#include "kernel/mini_uart.h" + +void enable_interrupt_controller (void); + +void show_invalid_entry_message (int type, ptr_t esr, ptr_t address); + +void irq_vector_init (void); + +void enable_irq (void); + +void disable_irq (void); + +#endif /*_ROSE_K_IRQ_H */ diff --git a/bulb/include/kernel/mini_uart.h b/bulb/include/kernel/mini_uart.h new file mode 100644 index 0000000..46499cf --- /dev/null +++ b/bulb/include/kernel/mini_uart.h @@ -0,0 +1,33 @@ +#ifndef _ROSE_K_UART_H +#ifndef _ROSE_K_MINI_UART_H +#define _ROSE_K_MINI_UART_H + +#include "common/gpu.h" +#include "common/stdbool.h" +#include "common/utils.h" +#include "kernel/peripherals/gpio.h" +#include "kernel/peripherals/mini_uart.h" +//#include "kernel/power.h" + +void mini_uart_init (void); + +char mini_uart_recv (void); + +void mini_uart_send (char c); + +void mini_uart_send_string (char * str); + +void handle_mini_uart_irq (void); + +// This function is required by printf function +void mini_putc (void * p, char c); + +#define uart_init mini_uart_init +#define uart_recv mini_uart_recv +#define uart_send mini_uart_send +#define uart_send_string mini_uart_send_string + +#define putc mini_putc + +#endif /*_ROSE_K_MINI_UART_H */ +#endif /*_ROSE_K_UART_H */ diff --git a/bulb/include/kernel/mmu.h b/bulb/include/kernel/mmu.h index 471bb20..ffa6200 100644 --- a/bulb/include/kernel/mmu.h +++ b/bulb/include/kernel/mmu.h @@ -1,9 +1,12 @@ #ifndef _ROSE_MMU_H #define _ROSE_MMU_H +#ifndef __ASSEMBLER__ + // Implementation taken from // https://github.com/bztsrc/raspi3-tutorial/blob/master/10_virtualmemory/mmu.c +#include "common/font.h" #include "common/logging.h" #include "common/status_led.h" #include "kernel/peripherals/base.h" @@ -36,10 +39,7 @@ extern volatile unsigned char _end; void init_mmu (void); -static char msg[] = "tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt889898ttttttttttttttttttttttttttttttttttttttttttttttttt908ttttttttttttttttttttttttttttttttttttttt+-" - "tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt889898ttttttttttttttttttttttttttttttttttttttttttttttttt908ttttttttttttttttttttttttttttttttttttttt+-" - "tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt889898ttttttttttttttttttttttttttttttttttttttttttttttttt908ttttttttttttttttttttttttttttttttttttttt+-" - "tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt889898ttttttttttttttttttttttttttttttttttttttttttttttttt908ttttttttttttttttttttttttttttttttttttttt+-" - "tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt889898ttttttttttttttttttttttttttttttttttttttttttttttttt908ttttttttttttttttttttttttttttttt########+-"; +void data_abort_el1 (ptr_t far, ptr_t esr); +#endif #endif//_ROSE_MMU_H \ No newline at end of file diff --git a/bulb/include/kernel/peripherals/irq.h b/bulb/include/kernel/peripherals/irq.h new file mode 100644 index 0000000..9900292 --- /dev/null +++ b/bulb/include/kernel/peripherals/irq.h @@ -0,0 +1,37 @@ +#ifndef _ROSE_K_P_IRQ_H +#define _ROSE_K_P_IRQ_H + +#include "kernel/peripherals/base.h" + +#define GIC_BASE 0xFF840000 +#define GICD_DIST_BASE (GIC_BASE + 0x00001000) +#define GICC_CPU_BASE (GIC_BASE + 0x00002000) + +#define GICD_ENABLE_IRQ_BASE (GICD_DIST_BASE + 0x00000100) + +#define GICC_IAR (GICC_CPU_BASE + 0x0000000C) +#define GICC_EOIR (GICC_CPU_BASE + 0x00000010) + +#define GIC_IRQ_TARGET_BASE (GICD_DIST_BASE + 0x00000800) + +//VC (=VideoCore) starts at 96 +#define SYSTEM_TIMER_IRQ_0 (0x60)//96 +#define SYSTEM_TIMER_IRQ_1 (0x61)//97 +#define SYSTEM_TIMER_IRQ_2 (0x62)//98 +#define SYSTEM_TIMER_IRQ_3 (0x63)//99 + +#define IRQ_BASIC_PENDING (PBASE + 0x0000B200) +#define IRQ_PENDING_1 (PBASE + 0x0000B204) +#define IRQ_PENDING_2 (PBASE + 0x0000B208) +#define FIQ_CONTROL (PBASE + 0x0000B20C) +#define ENABLE_IRQS_1 (PBASE + 0x0000B210) +#define ENABLE_IRQS_2 (PBASE + 0x0000B214) +#define ENABLE_BASIC_IRQS (PBASE + 0x0000B218) +#define DISABLE_IRQS_1 (PBASE + 0x0000B21C) +#define DISABLE_IRQS_2 (PBASE + 0x0000B220) +#define DISABLE_BASIC_IRQS (PBASE + 0x0000B224) + +#define MINI_UART_IRQ (1 << 0) +#define ENABLE_AUX_INT (1 << 29) + +#endif /*_ROSE_K_P_IRQ_H */ diff --git a/bulb/include/kernel/peripherals/mini_uart.h b/bulb/include/kernel/peripherals/mini_uart.h new file mode 100644 index 0000000..b065deb --- /dev/null +++ b/bulb/include/kernel/peripherals/mini_uart.h @@ -0,0 +1,25 @@ +#ifndef _ROSE_K_P_MINI_UART_H +#define _ROSE_K_P_MINI_UART_H + +#include "base.h" + +#define SYSTEM_CLOCK_FREQ 500000000 +#define BAUD_RATE_REG(target_baudrate) ((SYSTEM_CLOCK_FREQ / target_baudrate / 8) - 1) + +#define AUX_IRQ_REG (PBASE + 0x00215000) +#define AUX_ENABLES (PBASE + 0x00215004) +#define AUX_MU_IO_REG (PBASE + 0x00215040) +#define AUX_MU_IER_REG (PBASE + 0x00215044) +#define AUX_MU_IIR_REG (PBASE + 0x00215048) +#define AUX_MU_LCR_REG (PBASE + 0x0021504C) +#define AUX_MU_MCR_REG (PBASE + 0x00215050) +#define AUX_MU_LSR_REG (PBASE + 0x00215054) +#define AUX_MU_MSR_REG (PBASE + 0x00215058) +#define AUX_MU_SCRATCH (PBASE + 0x0021505C) +#define AUX_MU_CNTL_REG (PBASE + 0x00215060) +#define AUX_MU_STAT_REG (PBASE + 0x00215064) +#define AUX_MU_BAUD_REG (PBASE + 0x00215068) + +#define ENABLE_MU_REC_INT (0xFD) + +#endif /*_ROSE_K_P_MINI_UART_H */ diff --git a/bulb/src/kernel/entry.S b/bulb/src/kernel/entry.S new file mode 100644 index 0000000..604b0af --- /dev/null +++ b/bulb/src/kernel/entry.S @@ -0,0 +1,181 @@ +#include "kernel/arm/sysregs.h" +#include "kernel/entry.h" +#include "kernel/mmu.h" + + .macro handle_invalid_entry el, type + kernel_entry \el + mov x0, #\type + mrs x1, esr_el1 + mrs x2, elr_el1 + bl show_invalid_entry_message + b err_hang + .endm + + .macro ventry label + .align 7 + b \label + .endm + + .macro kernel_entry, el + sub sp, sp, #S_FRAME_SIZE + 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] + + .if \el == 0 + mrs x21, sp_el0 + .else + add x21, sp, #S_FRAME_SIZE + .endif /* \el == 0 */ + + mrs x22, elr_el1 + mrs x23, spsr_el1 + + stp x30, x21, [sp, #16 * 15] + stp x22, x23, [sp, #16 * 16] + .endm + + .macro kernel_exit, el + ldp x22, x23, [sp, #16 * 16] + ldp x30, x21, [sp, #16 * 15] + + .if \el == 0 + msr sp_el0, x21 + .endif /* \el == 0 */ + + msr elr_el1, x22 + msr spsr_el1, x23 + + + 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] + add sp, sp, #S_FRAME_SIZE + eret + .endm + + +/* + * Exception vectors. + */ +.align 11 +.globl vectors +vectors: + ventry sync_invalid_el1t // Synchronous EL1t + ventry irq_invalid_el1t // IRQ EL1t + ventry fiq_invalid_el1t // FIQ EL1t + ventry error_invalid_el1t // Error EL1t + + ventry sync_invalid_el1h // Synchronous EL1h + ventry el1_irq // IRQ EL1h + ventry fiq_invalid_el1h // FIQ EL1h + ventry error_invalid_el1h // Error EL1h + + ventry el0_sync // Synchronous 64-bit EL0 + ventry el0_irq // IRQ 64-bit EL0 + ventry fiq_invalid_el0_64 // FIQ 64-bit EL0 + ventry error_invalid_el0_64 // Error 64-bit EL0 + + ventry sync_invalid_el0_32 // Synchronous 32-bit EL0 + ventry irq_invalid_el0_32 // IRQ 32-bit EL0 + ventry fiq_invalid_el0_32 // FIQ 32-bit EL0 + ventry error_invalid_el0_32 // Error 32-bit EL0 + +sync_invalid_el1t: + handle_invalid_entry 1, SYNC_INVALID_EL1t + +irq_invalid_el1t: + handle_invalid_entry 1, IRQ_INVALID_EL1t + +fiq_invalid_el1t: + handle_invalid_entry 1, FIQ_INVALID_EL1t + +error_invalid_el1t: + handle_invalid_entry 1, ERROR_INVALID_EL1t + +sync_invalid_el1h: + handle_invalid_entry 1, SYNC_INVALID_EL1h + +fiq_invalid_el1h: + handle_invalid_entry 1, FIQ_INVALID_EL1h + +error_invalid_el1h: + handle_invalid_entry 1, ERROR_INVALID_EL1h + +fiq_invalid_el0_64: + handle_invalid_entry 0, FIQ_INVALID_EL0_64 + +error_invalid_el0_64: + handle_invalid_entry 0, ERROR_INVALID_EL0_64 + +sync_invalid_el0_32: + handle_invalid_entry 0, SYNC_INVALID_EL0_32 + +irq_invalid_el0_32: + handle_invalid_entry 0, IRQ_INVALID_EL0_32 + +fiq_invalid_el0_32: + handle_invalid_entry 0, FIQ_INVALID_EL0_32 + +error_invalid_el0_32: + handle_invalid_entry 0, ERROR_INVALID_EL0_32 + +el1_irq: + kernel_entry 1 + bl handle_irq + kernel_exit 1 + +el0_irq: + kernel_entry 0 + bl handle_irq + kernel_exit 0 + +el0_sync: + kernel_entry 0 + + mrs x25, esr_el1 + lsr x24, x25, #ESR_ELx_EC_SHIFT + cmp x24, #ESR_ELx_EC_DABT_SAME + b.eq el1_da + + handle_invalid_entry 0, SYNC_ERROR + +sc_nr .req x25 // number of system calls +scno .req x26 // syscall number +stbl .req x27 // syscall table pointer + +el1_da: + bl enable_irq + mrs x0, far_el1 + mrs x1, esr_el1 + bl data_abort_el1 + bl disable_irq + eret + +.globl err_hang +err_hang: b err_hang + diff --git a/bulb/src/kernel/irq.S b/bulb/src/kernel/irq.S new file mode 100644 index 0000000..ad54157 --- /dev/null +++ b/bulb/src/kernel/irq.S @@ -0,0 +1,15 @@ +.globl irq_vector_init +irq_vector_init: + adr x0, vectors // load VBAR_EL1 with virtual + msr vbar_el1, x0 // vector table address + ret + +.globl enable_irq +enable_irq: + msr daifclr, #2 + ret + +.globl disable_irq +disable_irq: + msr daifset, #2 + ret diff --git a/bulb/src/kernel/irq.c b/bulb/src/kernel/irq.c new file mode 100644 index 0000000..491ee73 --- /dev/null +++ b/bulb/src/kernel/irq.c @@ -0,0 +1,55 @@ +#include "kernel/irq.h" + +const char * entry_error_messages[] = { + "SYNC_INVALID_EL1t", "IRQ_INVALID_EL1t", "FIQ_INVALID_EL1t", "ERROR_INVALID_EL1T", "SYNC_INVALID_EL1h", "IRQ_INVALID_EL1h", "FIQ_INVALID_EL1h", "ERROR_INVALID_EL1h", "SYNC_INVALID_EL0_64", "IRQ_INVALID_EL0_64", "FIQ_INVALID_EL0_64", "ERROR_INVALID_EL0_64", "SYNC_INVALID_EL0_32", "IRQ_INVALID_EL0_32", "FIQ_INVALID_EL0_32", "ERROR_INVALID_EL0_32", "SYNC_ERROR", "SYSCALL_ERROR"}; + +void enable_interrupt (unsigned int irq) { + printf ("Interrupt pointer %p\r\n", irq); + unsigned int n = irq / 32; + unsigned int offset = irq % 32; + unsigned int enableRegister = GICD_ENABLE_IRQ_BASE + (4 * n); + printf ("EnableRegister: %x\r\n", enableRegister); + put32 (enableRegister, 1 << offset); +} + +void assign_target (unsigned int irq, unsigned int cpu) { + unsigned int n = irq / 4; + unsigned int targetRegister = GIC_IRQ_TARGET_BASE + (4 * n); + // Currently we only enter the target CPU 0 + put32 (targetRegister, get32 (targetRegister) | (1 << 8)); +} + +void show_invalid_entry_message (int type, ptr_t esr, ptr_t address) { + printf ("Type %s, ESR: %p, address, %p\r\n", entry_error_messages[type], (void *) esr, (void *) address); +} + +void enable_interrupt_controller () { + assign_target (SYSTEM_TIMER_IRQ_1, 0); + put32 (ENABLE_IRQS_1, SYSTEM_TIMER_IRQ_1 +#ifdef _ROSE_K_MINI_UART_H + | ENABLE_AUX_INT +#endif + ); + enable_interrupt (SYSTEM_TIMER_IRQ_1); +} + +void handle_irq (void) { + put32 (GICC_EOIR, get32 (GICC_IAR)); + /* + unsigned int irq_ack_reg = get32 (GICC_IAR); + unsigned int irq1 = irq_ack_reg & 0x2FF; + if (irq1 & SYSTEM_TIMER_IRQ_1) { + put32 (GICC_EOIR, irq_ack_reg); + handle_timer_irq (); + } + +#ifdef _ROSE_K_MINI_UART_H + unsigned int irq2 = get32 (AUX_IRQ_REG); + if (irq2 & MINI_UART_IRQ) { + put32 (GICC_EOIR, irq_ack_reg); + handle_mini_uart_irq (); + } + +#endif + */ +} diff --git a/bulb/src/kernel/kernel.c b/bulb/src/kernel/kernel.c index ab7eac3..efa2772 100644 --- a/bulb/src/kernel/kernel.c +++ b/bulb/src/kernel/kernel.c @@ -4,6 +4,9 @@ #include "common/printf.h" #include "common/status_led.h" #include "common/utils.h" +//#include "kernel/mini_uart.h" +#include "kernel/entry.h" +#include "kernel/irq.h" #include "kernel/mm.h" #include "kernel/mmu.h" @@ -14,10 +17,18 @@ void hang (int led, int cycles) { } } +void dual_print (void * p, char c) { + printc (c); + // uart_send (c); +} + void kernel_init (void) { set_led (0, POWER_LED); set_led (0, STATUS_LED); + // uart_init (); + // init_printf (0, putc); + if (init_gpu ()) { if (get_fb ()) { font_set_normal (); @@ -32,6 +43,11 @@ void kernel_init (void) { hang (POWER_LED, 1000000); } else hang (POWER_LED, 2000000); + init_printf (0, dual_print); + + irq_vector_init (); + enable_interrupt_controller (); + enable_irq (); } void kernel_main (int processor_id) { diff --git a/bulb/src/kernel/mini_uart.c b/bulb/src/kernel/mini_uart.c new file mode 100644 index 0000000..92273d7 --- /dev/null +++ b/bulb/src/kernel/mini_uart.c @@ -0,0 +1,88 @@ +#include "kernel/mini_uart.h" +/* +void mini_uart_send (char c) { + while (1) { + if (get32 (AUX_MU_LSR_REG) & 0x20) { + break; + } + } + put32 (AUX_MU_IO_REG, c); +} + +char mini_uart_recv (void) { + while (1) { + if (get32 (AUX_MU_LSR_REG) & 0x01) { + break; + } + } + return (get32 (AUX_MU_IO_REG) & 0xFF); +} + +void mini_uart_send_string (char * str) { + for (int i = 0; str[i] != '\0'; i++) { + mini_uart_send ((char) str[i]); + } +} + +void mini_uart_init (void) { + static volatile bool init_progress = false; + static volatile bool init_done = false; + + if (init_progress) { + while (!init_done) + ; + return; + } + init_progress = true; + + unsigned int selector; + int target = BAUD_RATE_REG (115200); + + selector = get32 (GPFSEL1); + selector &= ~(7 << 12); + selector |= 2 << 12; + selector &= ~(7 << 15); + selector |= 2 << 15; + put32 (GPFSEL1, selector); + + put32 (GPPUD, 0); + delay (150); + put32 (GPPUDCLK0, (1 << 14) | (1 << 15)); + delay (150); + put32 (GPPUDCLK0, 0); + + put32 (AUX_ENABLES, 1); + put32 (AUX_MU_CNTL_REG, 0); + put32 (AUX_MU_IER_REG, ENABLE_MU_REC_INT); + put32 (AUX_MU_LCR_REG, 3); + put32 (AUX_MU_MCR_REG, 0); + put32 (AUX_MU_BAUD_REG, target); + + put32 (AUX_MU_CNTL_REG, 3); + + mini_uart_send_string ("\033[2J\033[H"); + mini_uart_send_string ("Initialised mini UART\r\n"); + + init_done = true; +} + +//void handle_mini_uart_irq (void) { +// char c_event = mini_uart_recv (); +// switch (c_event) { +// case 17:// device control 1 +// mini_uart_send_string ("Power off"); +// poweroff (40, true);// power off instantly, never return control here +// case 18: // device control 2 +// mini_uart_send_string ("Reboot"); +// reboot (40, true);// reboot instantly, never return control here +// case 19: +// toggle_blank_screen (); +// default: +// mini_uart_send (c_event); +// } +//} + +void mini_putc (void * p, char c) { + mini_uart_send (c); +} + */ \ No newline at end of file diff --git a/bulb/src/kernel/mmu.c b/bulb/src/kernel/mmu.c index 03a6afc..6c7ae07 100644 --- a/bulb/src/kernel/mmu.c +++ b/bulb/src/kernel/mmu.c @@ -60,7 +60,7 @@ void init_mmu () { // kernel L3 paging[5 * 512] = (unsigned long) (PBASE + 0x00201000) |// physical address - PT_PAGE | // map 4k + PT_BLOCK | // map 4k PT_AF | // accessed flag PT_NX | // no execute PT_KERNEL | // privileged @@ -68,8 +68,6 @@ void init_mmu () { PT_DEV; // device memory /* okay, now we have to set system registers to enable MMU */ - // hang (POWER_LED, 2000000); - // check for 4k granule and at least 36 bits physical address bus */ asm volatile("mrs %0, id_aa64mmfr0_el1" : "=r"(r)); @@ -142,15 +140,43 @@ void init_mmu () { : : "r"(r)); - LOG ("Set SCTLR flags and enable MMU"); + // LOG ("Set SCTLR flags and enable MMU"); + // printf ("Printing non-aborting data: %d\r\n", *(char *) 0x000000001234abcd); + printf ((char *) 0xFFFF000000080000); - while (1) { - printc ('.'); - } - // printf (msg); - // printf ("test"); set_led (POWER_LED, 1); - hang (STATUS_LED, 2000000); + while (1) { + toggle_led (STATUS_LED); + delay (1000000); + } +} + +void data_abort_el1 (ptr_t far, ptr_t esr) { + byte_t type = (esr >> 2) & 0b11; + byte_t level = esr & 0b11; + // esr &= 0b111111; + + printf ("EL 1 - "); + printf ("FAR_EL1: %p - ", far); + printf ("ESR_EL1: %b\n\r", esr); + + switch (type) { + case 0b00:// Address size fault + printf ("Address size fault during level %ld of table walk on lookup of address %p.\r\n", level, far); + // exit_process (); + break; + case 0b01:// Translation fault + printf ("Translation fault during level %ld of table walk on lookup of address %p.\r\n", level, far); + break; + case 0b10:// Access flag fault + printf ("Access flag fault during level %ld of table walk on lookup of address %p.\r\n", level, far); + // exit_process (); + break; + case 0b11:// Permission fault + printf ("Segmentation fault during level %ld of table walk on lookup of address %p.\r\n", level, far); + // exit_process (); + break; + } } \ No newline at end of file From 8342385c446d40674cfce2f5ea2de2357ef8d1ce Mon Sep 17 00:00:00 2001 From: Aaron Alef Date: Wed, 3 Nov 2021 13:28:34 +0100 Subject: [PATCH 05/21] refactor(mmu): initialise PGD0 tables for kernel --- bulb/include/kernel/mmu.h | 3 + bulb/src/kernel/mmu.c | 149 ++++++++++++++++++++++++-------------- 2 files changed, 97 insertions(+), 55 deletions(-) diff --git a/bulb/include/kernel/mmu.h b/bulb/include/kernel/mmu.h index ffa6200..a7fb810 100644 --- a/bulb/include/kernel/mmu.h +++ b/bulb/include/kernel/mmu.h @@ -37,6 +37,9 @@ extern volatile unsigned char _data; extern volatile unsigned char _end; +static volatile unsigned int __attribute__ ((aligned (16))) buffer[32]; + +void init_pages (unsigned long * r, unsigned long * b); void init_mmu (void); void data_abort_el1 (ptr_t far, ptr_t esr); diff --git a/bulb/src/kernel/mmu.c b/bulb/src/kernel/mmu.c index 6c7ae07..07bf9a7 100644 --- a/bulb/src/kernel/mmu.c +++ b/bulb/src/kernel/mmu.c @@ -1,71 +1,107 @@ #include "kernel/mmu.h" -void init_mmu () { - unsigned long data_page = (unsigned long) &_data / PAGESIZE; - unsigned long r, b, *paging = (unsigned long *) &_end; +static volatile unsigned int buffer[] = {32, 0, 0x00038041, 8, 0, 42, 1, 0}; - /* create MMU translation tables at _end */ +void init_pages (unsigned long * r, unsigned long * b) { + unsigned long data_page = (unsigned long) &_data / PAGESIZE; + unsigned long * paging = (unsigned long *) &_end; + + // unsigned long * PGD0 = paging + 0 * 512; + // unsigned long * PGD1 = paging + 1 * 512; + unsigned long * PUD0 = paging + 0 * 512; + unsigned long * PUD1 = paging + 1 * 512; + unsigned long * PMD0 = paging + 2 * 512; + unsigned long * PMD1 = paging + 4 * 512; + unsigned long * PTE0 = paging + 3 * 512; + unsigned long * PTE1 = paging + 5 * 512; + /* create MMU translation tables at _end */ // TTBR0, identity L1 - paging[0] = (unsigned long) ((unsigned char *) &_end + 2 * PAGESIZE) |// physical address - PT_PAGE | // it has the "Present" flag, which must be set, and we have area in it mapped by pages - PT_AF | // accessed flag. Without this we're going to have a Data Abort exception - PT_USER | // non-privileged - PT_ISH | // inner shareable - PT_MEM; // normal memory + PUD0[0] = (unsigned long) ((unsigned char *) &_end + 2 * PAGESIZE) |// physical address + PT_PAGE | // it has the "Present" flag, which must be set, and we have area in it mapped by pages + PT_AF | // accessed flag. Without this we're going to have a Data Abort exception + PT_USER | // non-privileged + PT_ISH | // inner shareable + PT_MEM; // normal memory // identity L2, first 2M block - paging[2 * 512] = (unsigned long) ((unsigned char *) &_end + 3 * PAGESIZE) |// physical address - PT_PAGE | // we have area in it mapped by pages - PT_AF | // accessed flag - PT_USER | // non-privileged - PT_ISH | // inner shareable - PT_MEM; // normal memory + PMD0[0] = (unsigned long) ((unsigned char *) &_end + 3 * PAGESIZE) |// physical address + PT_PAGE | // we have area in it mapped by pages + PT_AF | // accessed flag + PT_USER | // non-privileged + PT_ISH | // inner shareable + PT_MEM; // normal memory // identity L2 2M blocks - b = PBASE >> 21; + *b = PBASE >> 21; // skip 0th, as we're about to map it by L3 - for (r = 1; r < 512; r++) - paging[2 * 512 + r] = (unsigned long) ((r << 21)) | // physical address - PT_BLOCK | // map 2M block - PT_AF | // accessed flag - PT_NX | // no execute - PT_USER | // non-privileged - (r >= b ? PT_OSH | PT_DEV : PT_ISH | PT_MEM);// different attributes for device memory + for (*r = 1; *r < 512; (*r)++) + PMD0[*r] = (unsigned long) (((*r) << 21)) | // physical address + PT_BLOCK | // map 2M block + PT_AF | // accessed flag + PT_NX | // no execute + PT_USER | // non-privileged + (*r >= *b ? PT_OSH | PT_DEV : PT_ISH | PT_MEM);// different attributes for device memory // identity L3 - for (r = 0; r < 512; r++) - paging[3 * 512 + r] = (unsigned long) (r * PAGESIZE) | // physical address - PT_PAGE | // map 4k - PT_AF | // accessed flag - PT_USER | // non-privileged - PT_ISH | // inner shareable - ((r < 0x80 || r >= data_page) ? PT_RW | PT_NX : PT_RO);// different for code and data - + for (*r = 0; *r < 512; (*r)++) + PTE0[*r] = (unsigned long) (*r * PAGESIZE) | // physical address + PT_PAGE | // map 4k + PT_AF | // accessed flag + PT_USER | // non-privileged + PT_ISH | // inner shareable + ((*r < 0x80 || *r >= data_page) ? PT_RW | PT_NX : PT_RO);// different for code and data + + /* // TTBR1, kernel L1 - paging[512 + 511] = (unsigned long) ((unsigned char *) &_end + 4 * PAGESIZE) |// physical address - PT_PAGE | // we have area in it mapped by pages - PT_AF | // accessed flag - PT_KERNEL | // privileged - PT_ISH | // inner shareable - PT_MEM; // normal memory + PUD1[0] = (unsigned long) ((unsigned char *) &_end + 4 * PAGESIZE) |// physical address + PT_PAGE | // we have area in it mapped by pages + PT_AF | // accessed flag + PT_KERNEL | // privileged + PT_ISH | // inner shareable + PT_MEM; // normal memory // kernel L2 - paging[4 * 512 + 511] = (unsigned long) ((unsigned char *) &_end + 5 * PAGESIZE) |// physical address - PT_PAGE | // we have area in it mapped by pages - PT_AF | // accessed flag - PT_KERNEL | // privileged - PT_ISH | // inner shareable - PT_MEM; // normal memory + PMD1[0] = (unsigned long) ((unsigned char *) &_end + 5 * PAGESIZE) |// physical address + PT_PAGE | // we have area in it mapped by pages + PT_AF | // accessed flag + PT_KERNEL | // privileged + PT_ISH | // inner shareable + PT_MEM; // normal memory + + // kernel L2 + PMD1[511] = (unsigned long) ((unsigned char *) &_end + 5 * PAGESIZE) |// physical address + PT_PAGE | // we have area in it mapped by pages + PT_AF | // accessed flag + PT_KERNEL | // privileged + PT_ISH | // inner shareable + PT_MEM; // normal memory + + // kernel L3 + PTE1[0] = (unsigned long) (PBASE + 0x00201000) |// physical address + PT_PAGE | // map 4k + PT_AF | // accessed flag + PT_NX | // no execute + PT_KERNEL | // privileged + PT_OSH | // outter shareable + PT_DEV; // device memory // kernel L3 - paging[5 * 512] = (unsigned long) (PBASE + 0x00201000) |// physical address - PT_BLOCK | // map 4k - PT_AF | // accessed flag - PT_NX | // no execute - PT_KERNEL | // privileged - PT_OSH | // outter shareable - PT_DEV; // device memory + PTE1[511] = (unsigned long) (PBASE + 0x00201000) |// physical address + PT_PAGE | // map 4k + PT_AF | // accessed flag + PT_NX | // no execute + PT_KERNEL | // privileged + PT_OSH | // outter shareable + PT_DEV; // device memory + */ +} + +void init_mmu () { + unsigned long data_page = (unsigned long) &_data / PAGESIZE; + unsigned long r, b, *paging = (unsigned long *) &_end; + + init_pages (&r, &b); /* okay, now we have to set system registers to enable MMU */ // check for 4k granule and at least 36 bits physical address bus */ @@ -117,7 +153,7 @@ void init_mmu () { // upper half, kernel space asm volatile("msr ttbr1_el1, %0" : - : "r"((unsigned long) &_end + TTBR_CNP + PAGESIZE)); + : "r"((unsigned long) &_end + TTBR_CNP)); LOG ("TTBR1 written"); // finally, toggle some bits in system control register to enable page translation @@ -140,10 +176,13 @@ void init_mmu () { : : "r"(r)); - // LOG ("Set SCTLR flags and enable MMU"); - // printf ("Printing non-aborting data: %d\r\n", *(char *) 0x000000001234abcd); - printf ((char *) 0xFFFF000000080000); + LOG ("Set SCTLR flags and enable MMU"); + *((unsigned int volatile *) (0xFE00B8A0)); + LOG ("LED SWITCHING DONE"); + + delay (100); + LOG ("TEST"); set_led (POWER_LED, 1); From 447dbd47b23a138453845f3df2e2d8d8e815de47 Mon Sep 17 00:00:00 2001 From: Aaron Alef Date: Wed, 3 Nov 2021 15:27:59 +0100 Subject: [PATCH 06/21] fix(mmu): correctly initialise tables, esp. peripheral base Printing + manual switching of LEDs works now --- bulb/include/common/font.h | 2 +- bulb/src/kernel/entry.S | 12 ++-- bulb/src/kernel/mmu.c | 126 +++++++++++++------------------------ 3 files changed, 50 insertions(+), 90 deletions(-) diff --git a/bulb/include/common/font.h b/bulb/include/common/font.h index b732416..0791dde 100644 --- a/bulb/include/common/font.h +++ b/bulb/include/common/font.h @@ -2,7 +2,7 @@ #define _ROSE_C_FONT_H #define FONT_SIZE 8 -#define FONT_FACTOR 2 +#define FONT_FACTOR 4 #define FONT_REAL_WIDTH (FONT_SIZE * FONT_FACTOR) // Spacing between lines in pixels diff --git a/bulb/src/kernel/entry.S b/bulb/src/kernel/entry.S index 604b0af..7198926 100644 --- a/bulb/src/kernel/entry.S +++ b/bulb/src/kernel/entry.S @@ -90,20 +90,20 @@ vectors: ventry fiq_invalid_el1t // FIQ EL1t ventry error_invalid_el1t // Error EL1t - ventry sync_invalid_el1h // Synchronous EL1h - ventry el1_irq // IRQ EL1h + ventry sync_invalid_el1h // Synchronous EL1h + ventry el1_irq // IRQ EL1h ventry fiq_invalid_el1h // FIQ EL1h ventry error_invalid_el1h // Error EL1h - ventry el0_sync // Synchronous 64-bit EL0 - ventry el0_irq // IRQ 64-bit EL0 + ventry el0_sync // Synchronous 64-bit EL0 + ventry el0_irq // IRQ 64-bit EL0 ventry fiq_invalid_el0_64 // FIQ 64-bit EL0 - ventry error_invalid_el0_64 // Error 64-bit EL0 + ventry error_invalid_el0_64 // Error 64-bit EL0 ventry sync_invalid_el0_32 // Synchronous 32-bit EL0 ventry irq_invalid_el0_32 // IRQ 32-bit EL0 ventry fiq_invalid_el0_32 // FIQ 32-bit EL0 - ventry error_invalid_el0_32 // Error 32-bit EL0 + ventry error_invalid_el0_32 // Error 32-bit EL0 sync_invalid_el1t: handle_invalid_entry 1, SYNC_INVALID_EL1t diff --git a/bulb/src/kernel/mmu.c b/bulb/src/kernel/mmu.c index 07bf9a7..0508c4f 100644 --- a/bulb/src/kernel/mmu.c +++ b/bulb/src/kernel/mmu.c @@ -6,95 +6,47 @@ void init_pages (unsigned long * r, unsigned long * b) { unsigned long data_page = (unsigned long) &_data / PAGESIZE; unsigned long * paging = (unsigned long *) &_end; - // unsigned long * PGD0 = paging + 0 * 512; - // unsigned long * PGD1 = paging + 1 * 512; unsigned long * PUD0 = paging + 0 * 512; - unsigned long * PUD1 = paging + 1 * 512; unsigned long * PMD0 = paging + 2 * 512; - unsigned long * PMD1 = paging + 4 * 512; - unsigned long * PTE0 = paging + 3 * 512; - unsigned long * PTE1 = paging + 5 * 512; + unsigned long * PTE0 = paging + 1 * 512; /* create MMU translation tables at _end */ // TTBR0, identity L1 - PUD0[0] = (unsigned long) ((unsigned char *) &_end + 2 * PAGESIZE) |// physical address - PT_PAGE | // it has the "Present" flag, which must be set, and we have area in it mapped by pages - PT_AF | // accessed flag. Without this we're going to have a Data Abort exception - PT_USER | // non-privileged - PT_ISH | // inner shareable - PT_MEM; // normal memory + *b = PBASE >> 21; + for (int i = 0; i < 8; i++) { + PUD0[i] = (unsigned long) ((unsigned char *) &_end + (2 + i) * PAGESIZE) |// physical address + PT_PAGE | // it has the "Present" flag, which must be set, and we have area in it mapped by pages + PT_AF | // accessed flag. Without this we're going to have a Data Abort exception + PT_USER | // non-privileged + PT_ISH | // inner shareable + PT_MEM; // normal memory + + unsigned int offset = i * 512; + // identity L2 2M blocks + for (*r = 0; *r < 512; (*r)++) + PMD0[i * 512 + *r] = (unsigned long) ((offset + *r) << 21) | // physical address + PT_BLOCK | // map 2M block + PT_AF | // accessed flag + PT_USER | // non-privileged + (offset + *r >= *b ? PT_OSH | PT_DEV : PT_ISH | PT_MEM);// different attributes for device memory + } // identity L2, first 2M block - PMD0[0] = (unsigned long) ((unsigned char *) &_end + 3 * PAGESIZE) |// physical address - PT_PAGE | // we have area in it mapped by pages - PT_AF | // accessed flag - PT_USER | // non-privileged - PT_ISH | // inner shareable - PT_MEM; // normal memory - - // identity L2 2M blocks - *b = PBASE >> 21; - // skip 0th, as we're about to map it by L3 - for (*r = 1; *r < 512; (*r)++) - PMD0[*r] = (unsigned long) (((*r) << 21)) | // physical address - PT_BLOCK | // map 2M block - PT_AF | // accessed flag - PT_NX | // no execute - PT_USER | // non-privileged - (*r >= *b ? PT_OSH | PT_DEV : PT_ISH | PT_MEM);// different attributes for device memory + PMD0[0] = (unsigned long) ((unsigned char *) &_end + PAGESIZE) |// physical address + PT_PAGE | // we have area in it mapped by pages + PT_AF | // accessed flag + PT_USER | // non-privileged + PT_ISH | // inner shareable + PT_MEM; // normal memory // identity L3 for (*r = 0; *r < 512; (*r)++) - PTE0[*r] = (unsigned long) (*r * PAGESIZE) | // physical address - PT_PAGE | // map 4k - PT_AF | // accessed flag - PT_USER | // non-privileged - PT_ISH | // inner shareable - ((*r < 0x80 || *r >= data_page) ? PT_RW | PT_NX : PT_RO);// different for code and data - - /* - // TTBR1, kernel L1 - PUD1[0] = (unsigned long) ((unsigned char *) &_end + 4 * PAGESIZE) |// physical address - PT_PAGE | // we have area in it mapped by pages - PT_AF | // accessed flag - PT_KERNEL | // privileged - PT_ISH | // inner shareable - PT_MEM; // normal memory - - // kernel L2 - PMD1[0] = (unsigned long) ((unsigned char *) &_end + 5 * PAGESIZE) |// physical address - PT_PAGE | // we have area in it mapped by pages - PT_AF | // accessed flag - PT_KERNEL | // privileged - PT_ISH | // inner shareable - PT_MEM; // normal memory - - // kernel L2 - PMD1[511] = (unsigned long) ((unsigned char *) &_end + 5 * PAGESIZE) |// physical address - PT_PAGE | // we have area in it mapped by pages - PT_AF | // accessed flag - PT_KERNEL | // privileged - PT_ISH | // inner shareable - PT_MEM; // normal memory - - // kernel L3 - PTE1[0] = (unsigned long) (PBASE + 0x00201000) |// physical address - PT_PAGE | // map 4k - PT_AF | // accessed flag - PT_NX | // no execute - PT_KERNEL | // privileged - PT_OSH | // outter shareable - PT_DEV; // device memory - - // kernel L3 - PTE1[511] = (unsigned long) (PBASE + 0x00201000) |// physical address - PT_PAGE | // map 4k - PT_AF | // accessed flag - PT_NX | // no execute - PT_KERNEL | // privileged - PT_OSH | // outter shareable - PT_DEV; // device memory - */ + PTE0[*r] = (unsigned long) (*r * PAGESIZE) | // physical address + PT_PAGE | // map 4k + PT_AF | // accessed flag + PT_USER | // non-privileged + PT_ISH | // inner shareable + ((*r < 0x80 || *r >= data_page) ? PT_RW : PT_RO);// different for code and data } void init_mmu () { @@ -171,18 +123,26 @@ void init_mmu () { r |= (1 << 0); // set M, enable MMU LOG ("Read out system control register"); + printf ("Current status LED status: %l\r\n", get_led (STATUS_LED)); asm volatile("msr sctlr_el1, %0; isb" : : "r"(r)); LOG ("Set SCTLR flags and enable MMU"); - *((unsigned int volatile *) (0xFE00B8A0)); - LOG ("LED SWITCHING DONE"); - delay (100); + *((unsigned int volatile *) (0xFE00B8A0)) = (unsigned long) buffer | 8; + LOG ("LED SWITCHING DONE"); - LOG ("TEST"); + printf ("Msg : %p\r\n", (unsigned long) buffer | 8); + printf ("%u ", buffer[0]); + printf ("%u ", buffer[1]); + printf ("%p ", buffer[2]); + printf ("%u ", buffer[3]); + printf ("%u ", buffer[4]); + printf ("%u ", buffer[5]); + printf ("%u ", buffer[6]); + printf ("%u \r\n", buffer[7]); set_led (POWER_LED, 1); From 4a930b0d7d87520bc2c0d5e365d2ed3b02522f1e Mon Sep 17 00:00:00 2001 From: Aaron Alef Date: Wed, 3 Nov 2021 15:31:24 +0100 Subject: [PATCH 07/21] refactor(mmu): removed weird passing of r and b by reference --- bulb/include/kernel/mmu.h | 4 +++- bulb/src/kernel/mmu.c | 38 +++++++++++++++++++------------------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/bulb/include/kernel/mmu.h b/bulb/include/kernel/mmu.h index a7fb810..408f210 100644 --- a/bulb/include/kernel/mmu.h +++ b/bulb/include/kernel/mmu.h @@ -33,13 +33,15 @@ #define TTBR_CNP 1 +#define RAM_IN_GB 8 + // get addresses from linker extern volatile unsigned char _data; extern volatile unsigned char _end; static volatile unsigned int __attribute__ ((aligned (16))) buffer[32]; -void init_pages (unsigned long * r, unsigned long * b); +void init_pages (); void init_mmu (void); void data_abort_el1 (ptr_t far, ptr_t esr); diff --git a/bulb/src/kernel/mmu.c b/bulb/src/kernel/mmu.c index 0508c4f..8945481 100644 --- a/bulb/src/kernel/mmu.c +++ b/bulb/src/kernel/mmu.c @@ -2,9 +2,9 @@ static volatile unsigned int buffer[] = {32, 0, 0x00038041, 8, 0, 42, 1, 0}; -void init_pages (unsigned long * r, unsigned long * b) { - unsigned long data_page = (unsigned long) &_data / PAGESIZE; - unsigned long * paging = (unsigned long *) &_end; +void init_pages () { + unsigned long data_page = (unsigned long) &_data / PAGESIZE; + unsigned long r, b, *paging = (unsigned long *) &_end; unsigned long * PUD0 = paging + 0 * 512; unsigned long * PMD0 = paging + 2 * 512; @@ -12,8 +12,8 @@ void init_pages (unsigned long * r, unsigned long * b) { /* create MMU translation tables at _end */ // TTBR0, identity L1 - *b = PBASE >> 21; - for (int i = 0; i < 8; i++) { + b = PBASE >> 21; + for (int i = 0; i < RAM_IN_GB; i++) { PUD0[i] = (unsigned long) ((unsigned char *) &_end + (2 + i) * PAGESIZE) |// physical address PT_PAGE | // it has the "Present" flag, which must be set, and we have area in it mapped by pages PT_AF | // accessed flag. Without this we're going to have a Data Abort exception @@ -23,12 +23,12 @@ void init_pages (unsigned long * r, unsigned long * b) { unsigned int offset = i * 512; // identity L2 2M blocks - for (*r = 0; *r < 512; (*r)++) - PMD0[i * 512 + *r] = (unsigned long) ((offset + *r) << 21) | // physical address - PT_BLOCK | // map 2M block - PT_AF | // accessed flag - PT_USER | // non-privileged - (offset + *r >= *b ? PT_OSH | PT_DEV : PT_ISH | PT_MEM);// different attributes for device memory + for (r = 0; r < 512; r++) + PMD0[i * 512 + r] = (unsigned long) ((offset + r) << 21) | // physical address + PT_BLOCK | // map 2M block + PT_AF | // accessed flag + PT_USER | // non-privileged + (offset + r >= b ? PT_OSH | PT_DEV : PT_ISH | PT_MEM);// different attributes for device memory } // identity L2, first 2M block @@ -40,20 +40,20 @@ void init_pages (unsigned long * r, unsigned long * b) { PT_MEM; // normal memory // identity L3 - for (*r = 0; *r < 512; (*r)++) - PTE0[*r] = (unsigned long) (*r * PAGESIZE) | // physical address - PT_PAGE | // map 4k - PT_AF | // accessed flag - PT_USER | // non-privileged - PT_ISH | // inner shareable - ((*r < 0x80 || *r >= data_page) ? PT_RW : PT_RO);// different for code and data + for (r = 0; r < 512; r++) + PTE0[r] = (unsigned long) (r * PAGESIZE) | // physical address + PT_PAGE | // map 4k + PT_AF | // accessed flag + PT_USER | // non-privileged + PT_ISH | // inner shareable + ((r < 0x80 || r >= data_page) ? PT_RW : PT_RO);// different for code and data } void init_mmu () { unsigned long data_page = (unsigned long) &_data / PAGESIZE; unsigned long r, b, *paging = (unsigned long *) &_end; - init_pages (&r, &b); + init_pages (); /* okay, now we have to set system registers to enable MMU */ // check for 4k granule and at least 36 bits physical address bus */ From c68ec3759a851963e2a5799a06a6c8e87a64c518 Mon Sep 17 00:00:00 2001 From: Aaron Alef Date: Wed, 3 Nov 2021 16:10:45 +0100 Subject: [PATCH 08/21] feat(bulb): enable (timer, uart) interrupts --- bulb/include/kernel/mmu.h | 1 + bulb/include/kernel/peripherals/power.h | 21 +++++++++++++++ bulb/include/kernel/peripherals/timer.h | 19 ++++++++++++++ bulb/include/kernel/power.h | 14 ++++++++++ bulb/include/kernel/timer.h | 8 ++++++ bulb/src/kernel/entry.S | 2 +- bulb/src/kernel/irq.c | 4 --- bulb/src/kernel/kernel.c | 13 +++++---- bulb/src/kernel/mini_uart.c | 35 ++++++++++++------------- bulb/src/kernel/mmu.c | 8 +----- bulb/src/kernel/power.c | 19 ++++++++++++++ bulb/src/kernel/timer.c | 23 ++++++++++++++++ 12 files changed, 132 insertions(+), 35 deletions(-) create mode 100644 bulb/include/kernel/peripherals/power.h create mode 100644 bulb/include/kernel/peripherals/timer.h create mode 100644 bulb/include/kernel/power.h create mode 100644 bulb/include/kernel/timer.h create mode 100644 bulb/src/kernel/power.c create mode 100644 bulb/src/kernel/timer.c diff --git a/bulb/include/kernel/mmu.h b/bulb/include/kernel/mmu.h index 408f210..b9537a6 100644 --- a/bulb/include/kernel/mmu.h +++ b/bulb/include/kernel/mmu.h @@ -9,6 +9,7 @@ #include "common/font.h" #include "common/logging.h" #include "common/status_led.h" +#include "kernel/mini_uart.h" #include "kernel/peripherals/base.h" #define PAGESIZE 4096 diff --git a/bulb/include/kernel/peripherals/power.h b/bulb/include/kernel/peripherals/power.h new file mode 100644 index 0000000..b02469f --- /dev/null +++ b/bulb/include/kernel/peripherals/power.h @@ -0,0 +1,21 @@ +#ifndef _ROSE_K_P_POWER_H +#define _ROSE_K_P_POWER_H + +#include "kernel/peripherals/base.h" + +#define PM_BASE PBASE + 0x100000 + +#define PM_RSTC PM_BASE + 0x1c +#define PM_WDOG PM_BASE + 0x24 + +#define PM_WDOG_RESET 0000000000 +#define PM_PASSWORD 0x5a000000 +#define PM_WDOG_TIME_SET 0x000fffff +#define PM_RSTC_WRCFG_CLR 0xffffffcf +#define PM_RSTC_WRCFG_SET 0x00000030 +#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 +#define PM_RSTC_RESET 0x00000102 + +#endif//_ROSE_K_P_POWER_H + +/* Copyright (C) 2020 Aaron Alef */ \ No newline at end of file diff --git a/bulb/include/kernel/peripherals/timer.h b/bulb/include/kernel/peripherals/timer.h new file mode 100644 index 0000000..ae3bf7f --- /dev/null +++ b/bulb/include/kernel/peripherals/timer.h @@ -0,0 +1,19 @@ +#ifndef _ROSE_K_P_TIMER_H +#define _ROSE_K_P_TIMER_H + +#include "kernel/peripherals/base.h" + +#define TIMER_CS (PBASE + 0x00003000) +#define TIMER_CLO (PBASE + 0x00003004) +#define TIMER_CHI (PBASE + 0x00003008) +#define TIMER_C0 (PBASE + 0x0000300C) +#define TIMER_C1 (PBASE + 0x00003010) +#define TIMER_C2 (PBASE + 0x00003014) +#define TIMER_C3 (PBASE + 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 /*_ROSE_K_P_TIMER_H */ diff --git a/bulb/include/kernel/power.h b/bulb/include/kernel/power.h new file mode 100644 index 0000000..031db9c --- /dev/null +++ b/bulb/include/kernel/power.h @@ -0,0 +1,14 @@ +#ifndef _ROSE_K_POWER_H +#define _ROSE_K_POWER_H + +#include "common/stdbool.h" +#include "common/utils.h" +#include "kernel/peripherals/power.h" + +// power off (timeout / 16 in seconds?) +void poweroff (unsigned int timeout, bool block); + +// reboot (timeout / 16 in seconds?) +void reboot (unsigned int timeout, bool block); + +#endif//_ROSE_K_POWER_H \ No newline at end of file diff --git a/bulb/include/kernel/timer.h b/bulb/include/kernel/timer.h new file mode 100644 index 0000000..f5cd0b8 --- /dev/null +++ b/bulb/include/kernel/timer.h @@ -0,0 +1,8 @@ +#ifndef _ROSE_K_TIMER_H +#define _ROSE_K_TIMER_H + +void timer_init (void); + +void handle_timer_irq (void); + +#endif /*_ROSE_K_TIMER_H */ diff --git a/bulb/src/kernel/entry.S b/bulb/src/kernel/entry.S index 7198926..dcbbce8 100644 --- a/bulb/src/kernel/entry.S +++ b/bulb/src/kernel/entry.S @@ -90,7 +90,7 @@ vectors: ventry fiq_invalid_el1t // FIQ EL1t ventry error_invalid_el1t // Error EL1t - ventry sync_invalid_el1h // Synchronous EL1h + ventry el0_sync // Synchronous EL1h ventry el1_irq // IRQ EL1h ventry fiq_invalid_el1h // FIQ EL1h ventry error_invalid_el1h // Error EL1h diff --git a/bulb/src/kernel/irq.c b/bulb/src/kernel/irq.c index 491ee73..7ca1047 100644 --- a/bulb/src/kernel/irq.c +++ b/bulb/src/kernel/irq.c @@ -34,8 +34,6 @@ void enable_interrupt_controller () { } void handle_irq (void) { - put32 (GICC_EOIR, get32 (GICC_IAR)); - /* unsigned int irq_ack_reg = get32 (GICC_IAR); unsigned int irq1 = irq_ack_reg & 0x2FF; if (irq1 & SYSTEM_TIMER_IRQ_1) { @@ -49,7 +47,5 @@ void handle_irq (void) { put32 (GICC_EOIR, irq_ack_reg); handle_mini_uart_irq (); } - #endif - */ } diff --git a/bulb/src/kernel/kernel.c b/bulb/src/kernel/kernel.c index efa2772..629c1a4 100644 --- a/bulb/src/kernel/kernel.c +++ b/bulb/src/kernel/kernel.c @@ -1,10 +1,11 @@ +#include "kernel/mini_uart.h" +// #include "common/font.h" #include "common/gpu.h" #include "common/logging.h" #include "common/printf.h" #include "common/status_led.h" #include "common/utils.h" -//#include "kernel/mini_uart.h" #include "kernel/entry.h" #include "kernel/irq.h" #include "kernel/mm.h" @@ -19,15 +20,15 @@ void hang (int led, int cycles) { void dual_print (void * p, char c) { printc (c); - // uart_send (c); + uart_send (c); } void kernel_init (void) { set_led (0, POWER_LED); set_led (0, STATUS_LED); - // uart_init (); - // init_printf (0, putc); + uart_init (); + init_printf (0, putc); if (init_gpu ()) { if (get_fb ()) { @@ -45,6 +46,7 @@ void kernel_init (void) { hang (POWER_LED, 2000000); init_printf (0, dual_print); + timer_init (); irq_vector_init (); enable_interrupt_controller (); enable_irq (); @@ -56,6 +58,7 @@ void kernel_main (int processor_id) { init_mmu (); printf ("Hello, from processor %d in EL %d\r\n", processor_id, get_el ()); + uart_send ("EVERYTHING WORKS!!!\r\n"); - hang (STATUS_LED, 5000000); + hang (POWER_LED, 5000000); } diff --git a/bulb/src/kernel/mini_uart.c b/bulb/src/kernel/mini_uart.c index 92273d7..64b005e 100644 --- a/bulb/src/kernel/mini_uart.c +++ b/bulb/src/kernel/mini_uart.c @@ -1,5 +1,5 @@ #include "kernel/mini_uart.h" -/* + void mini_uart_send (char c) { while (1) { if (get32 (AUX_MU_LSR_REG) & 0x20) { @@ -66,23 +66,22 @@ void mini_uart_init (void) { init_done = true; } -//void handle_mini_uart_irq (void) { -// char c_event = mini_uart_recv (); -// switch (c_event) { -// case 17:// device control 1 -// mini_uart_send_string ("Power off"); -// poweroff (40, true);// power off instantly, never return control here -// case 18: // device control 2 -// mini_uart_send_string ("Reboot"); -// reboot (40, true);// reboot instantly, never return control here -// case 19: -// toggle_blank_screen (); -// default: -// mini_uart_send (c_event); -// } -//} +void handle_mini_uart_irq (void) { + char c_event = mini_uart_recv (); + switch (c_event) { + case 17:// device control 1 + mini_uart_send_string ("Power off"); + poweroff (40, true);// power off instantly, never return control here + case 18: // device control 2 + mini_uart_send_string ("Reboot"); + reboot (40, true);// reboot instantly, never return control here + case 19: + toggle_blank_screen (); + default: + mini_uart_send (c_event); + } +} void mini_putc (void * p, char c) { mini_uart_send (c); -} - */ \ No newline at end of file +} \ No newline at end of file diff --git a/bulb/src/kernel/mmu.c b/bulb/src/kernel/mmu.c index 8945481..1e11103 100644 --- a/bulb/src/kernel/mmu.c +++ b/bulb/src/kernel/mmu.c @@ -123,7 +123,6 @@ void init_mmu () { r |= (1 << 0); // set M, enable MMU LOG ("Read out system control register"); - printf ("Current status LED status: %l\r\n", get_led (STATUS_LED)); asm volatile("msr sctlr_el1, %0; isb" : @@ -145,17 +144,12 @@ void init_mmu () { printf ("%u \r\n", buffer[7]); set_led (POWER_LED, 1); - - while (1) { - toggle_led (STATUS_LED); - delay (1000000); - } } void data_abort_el1 (ptr_t far, ptr_t esr) { byte_t type = (esr >> 2) & 0b11; byte_t level = esr & 0b11; - // esr &= 0b111111; + esr &= 0b111111; printf ("EL 1 - "); printf ("FAR_EL1: %p - ", far); diff --git a/bulb/src/kernel/power.c b/bulb/src/kernel/power.c new file mode 100644 index 0000000..bcfbc55 --- /dev/null +++ b/bulb/src/kernel/power.c @@ -0,0 +1,19 @@ +#include "kernel/power.h" + +void poweroff (unsigned int timeout, bool block) { +} + +void reboot (unsigned int timeout, bool block) { + unsigned int pm_rstc, pm_wdog; + + /* Setup watchdog for reset */ + pm_rstc = get32 (PM_RSTC); + // watchdog timer = timer clock / 16; need password (31:16) + value (11:0) + pm_wdog = PM_PASSWORD | (timeout & PM_WDOG_TIME_SET); + pm_rstc = PM_PASSWORD | (pm_rstc & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET; + put32 (PM_WDOG, pm_wdog); + put32 (PM_RSTC, pm_rstc); + + while (block) + ; +} diff --git a/bulb/src/kernel/timer.c b/bulb/src/kernel/timer.c new file mode 100644 index 0000000..0b3a5f6 --- /dev/null +++ b/bulb/src/kernel/timer.c @@ -0,0 +1,23 @@ +#include "kernel/peripherals/timer.h" +#include "common/printf.h" +#include "common/status_led.h" +#include "common/utils.h" +//#include "kernel/sched.h" + +const unsigned int interval = 200000; +unsigned int curVal = 0; + +void timer_init (void) { + curVal = get32 (TIMER_CLO); + curVal += interval; + put32 (TIMER_C1, curVal); +} + +void handle_timer_irq (void) { + toggle_led (STATUS_LED); + + curVal += interval; + put32 (TIMER_C1, curVal); + put32 (TIMER_CS, TIMER_CS_M1); + // timer_tick (); +} From c6f1c7f234a9bd8a29667efebfbf83c838b9a194 Mon Sep 17 00:00:00 2001 From: Aaron Alef Date: Wed, 3 Nov 2021 16:22:21 +0100 Subject: [PATCH 09/21] feat(mmu): initialise and enable mmu on thorn --- Makefile | 2 +- thorn/include/kernel/mmu.h | 51 ++++++++++++ thorn/src/kernel/boot.S | 4 +- thorn/src/kernel/kernel.c | 11 ++- thorn/src/kernel/mmu.c | 158 +++++++++++++++++++++++++++++++++++++ thorn/src/linker.ld | 17 ++-- 6 files changed, 231 insertions(+), 12 deletions(-) create mode 100644 thorn/include/kernel/mmu.h create mode 100644 thorn/src/kernel/mmu.c diff --git a/Makefile b/Makefile index 1ee03d7..e16cc6d 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ MNT_Darwin = /Volumes/boot #BOOT_PART = /dev/mmcblk0p1 # Serial connection config -SEND_DEFAULT_TARGET = bulb +SEND_DEFAULT_TARGET = thorn BAUD_RATE = 115200 SERIAL_PORT = $(SERIAL_PORT_$(HOST_OS)) SERIAL_PORT_ALT = $(SERIAL_PORT_ALT_$(HOST_OS)) diff --git a/thorn/include/kernel/mmu.h b/thorn/include/kernel/mmu.h new file mode 100644 index 0000000..b9537a6 --- /dev/null +++ b/thorn/include/kernel/mmu.h @@ -0,0 +1,51 @@ +#ifndef _ROSE_MMU_H +#define _ROSE_MMU_H + +#ifndef __ASSEMBLER__ + +// Implementation taken from +// https://github.com/bztsrc/raspi3-tutorial/blob/master/10_virtualmemory/mmu.c + +#include "common/font.h" +#include "common/logging.h" +#include "common/status_led.h" +#include "kernel/mini_uart.h" +#include "kernel/peripherals/base.h" + +#define PAGESIZE 4096 + +// granularity +#define PT_PAGE 0b11// 4k granule +#define PT_BLOCK 0b01// 2M granule +// accessibility +#define PT_KERNEL (0 << 6) // privileged, supervisor EL1 access only +#define PT_USER (1 << 6) // unprivileged, EL0 access allowed +#define PT_RW (0 << 7) // read-write +#define PT_RO (1 << 7) // read-only +#define PT_AF (1 << 10) // accessed flag +#define PT_NX (1UL << 54)// no execute +// shareability +#define PT_OSH (2 << 8)// outter shareable +#define PT_ISH (3 << 8)// inner shareable +// defined in MAIR register +#define PT_MEM (0 << 2)// normal memory +#define PT_DEV (1 << 2)// device MMIO +#define PT_NC (2 << 2)// non-cachable + +#define TTBR_CNP 1 + +#define RAM_IN_GB 8 + +// get addresses from linker +extern volatile unsigned char _data; +extern volatile unsigned char _end; + +static volatile unsigned int __attribute__ ((aligned (16))) buffer[32]; + +void init_pages (); +void init_mmu (void); + +void data_abort_el1 (ptr_t far, ptr_t esr); + +#endif +#endif//_ROSE_MMU_H \ No newline at end of file diff --git a/thorn/src/kernel/boot.S b/thorn/src/kernel/boot.S index abfd307..b83930e 100644 --- a/thorn/src/kernel/boot.S +++ b/thorn/src/kernel/boot.S @@ -15,8 +15,8 @@ _start: b master init_bss: - adr x0, bss_begin - adr x1, bss_end + adr x0, __bss_start + adr x1, __bss_end sub x1, x1, x0 bl memzero diff --git a/thorn/src/kernel/kernel.c b/thorn/src/kernel/kernel.c index 9e37699..ba50281 100644 --- a/thorn/src/kernel/kernel.c +++ b/thorn/src/kernel/kernel.c @@ -1,3 +1,5 @@ +#include "kernel/mini_uart.h" +// KEEP THIS #include "common/font.h" #include "common/gpu.h" #include "common/logging.h" @@ -8,8 +10,8 @@ #include "common/utils.h" #include "kernel/fork.h" #include "kernel/irq.h" -#include "kernel/mini_uart.h" #include "kernel/mm.h" +#include "kernel/mmu.h" #include "kernel/sched.h" #include "kernel/sys.h" #include "kernel/timer.h" @@ -88,9 +90,7 @@ void kernel_init (void) { printf ("Height resolution: %d\r\n", get_fb_info ()->virtual_height); } } - - printf ("|...|...|...|...|\r\n"); - printf ("|\t|\t|\t|\t|\r\n"); + init_pages (); LOG ("Initialisation done"); ERROR ("I'm important!"); @@ -106,6 +106,8 @@ void kernel_main (int processor_id) { // Synchronisation to prevent concurrent print while (processor_id != current_processor) {} printf ("Hello, from processor %d in EL %d\n\r", processor_id, get_el ()); + init_mmu (); + current_processor++; while (current_processor != 4) {} @@ -125,6 +127,7 @@ void kernel_main (int processor_id) { case 2: case 3: default: + while (1) {} printf ("Undefined behaviour on processor %d\r\n", processor_id); } printf ("Processor %d going out of scope\r\n", processor_id); diff --git a/thorn/src/kernel/mmu.c b/thorn/src/kernel/mmu.c new file mode 100644 index 0000000..d500828 --- /dev/null +++ b/thorn/src/kernel/mmu.c @@ -0,0 +1,158 @@ +#include "kernel/mmu.h" + +static volatile unsigned int buffer[] = {32, 0, 0x00038041, 8, 0, 42, 1, 0}; + +void init_pages () { + unsigned long data_page = (unsigned long) &_data / PAGESIZE; + unsigned long r, b, *paging = (unsigned long *) &_end; + + unsigned long * PUD0 = paging + 0 * 512; + unsigned long * PMD0 = paging + 2 * 512; + unsigned long * PTE0 = paging + 1 * 512; + + /* create MMU translation tables at _end */ + // TTBR0, identity L1 + b = PBASE >> 21; + for (int i = 0; i < RAM_IN_GB; i++) { + PUD0[i] = (unsigned long) ((unsigned char *) &_end + (2 + i) * PAGESIZE) |// physical address + PT_PAGE | // it has the "Present" flag, which must be set, and we have area in it mapped by pages + PT_AF | // accessed flag. Without this we're going to have a Data Abort exception + PT_USER | // non-privileged + PT_ISH | // inner shareable + PT_MEM; // normal memory + + unsigned int offset = i * 512; + // identity L2 2M blocks + for (r = 0; r < 512; r++) + PMD0[i * 512 + r] = (unsigned long) ((offset + r) << 21) | // physical address + PT_BLOCK | // map 2M block + PT_AF | // accessed flag + PT_USER | // non-privileged + (offset + r >= b ? PT_OSH | PT_DEV : PT_ISH | PT_MEM);// different attributes for device memory + } + + // identity L2, first 2M block + PMD0[0] = (unsigned long) ((unsigned char *) &_end + PAGESIZE) |// physical address + PT_PAGE | // we have area in it mapped by pages + PT_AF | // accessed flag + PT_USER | // non-privileged + PT_ISH | // inner shareable + PT_MEM; // normal memory + + // identity L3 + for (r = 0; r < 512; r++) + PTE0[r] = (unsigned long) (r * PAGESIZE) | // physical address + PT_PAGE | // map 4k + PT_AF | // accessed flag + PT_USER | // non-privileged + PT_ISH | // inner shareable + ((r < 0x80 || r >= data_page) ? PT_RW : PT_RO);// different for code and data +} + +void init_mmu () { + unsigned long data_page = (unsigned long) &_data / PAGESIZE; + unsigned long r, b, *paging = (unsigned long *) &_end; + + /* okay, now we have to set system registers to enable MMU */ + // check for 4k granule and at least 36 bits physical address bus */ + asm volatile("mrs %0, id_aa64mmfr0_el1" + : "=r"(r)); + b = r & 0xF; + if (r & (0xF << 28) /*4k*/ || b < 1 /*36 bits*/) { + ERROR ("ERROR: 4k granule or 36 bit address space not supported\n"); + return; + } + LOG ("4k granule and 36bit address bus ensured"); + + // first, set Memory Attributes array, indexed by PT_MEM, PT_DEV, PT_NC in our example + r = (0xFF << 0) |// AttrIdx=0: normal, IWBWA, OWBWA, NTR + (0x04 << 8) |// AttrIdx=1: device, nGnRE (must be OSH too) + (0x44 << 16);// AttrIdx=2: non cacheable + asm volatile("msr mair_el1, %0" + : + : "r"(r)); + LOG ("MAIR attributes written"); + + // next, specify mapping characteristics in translate control register + r = (0b00LL << 37) |// TBI=0, no tagging + (b << 32) | // IPS=autodetected + (0b10LL << 30) |// TG1=4k + (0b11LL << 28) |// SH1=3 inner + (0b01LL << 26) |// ORGN1=1 write back + (0b01LL << 24) |// IRGN1=1 write back + (0b0LL << 23) | // EPD1 enable higher half + (25LL << 16) | // T1SZ=25, 3 levels (512G) + (0b00LL << 14) |// TG0=4k + (0b11LL << 12) |// SH0=3 inner + (0b01LL << 10) |// ORGN0=1 write back + (0b01LL << 8) | // IRGN0=1 write back + (0b0LL << 7) | // EPD0 enable lower half + (25LL << 0); // T0SZ=25, 3 levels (512G) + asm volatile("msr tcr_el1, %0; isb" + : + : "r"(r)); + LOG ("Translation control register written"); + + // tell the MMU where our translation tables are. TTBR_CNP bit not documented, but required + // lower half, user space + asm volatile("msr ttbr0_el1, %0" + : + : "r"((unsigned long) &_end + TTBR_CNP)); + LOG ("TTBR0 written"); + + // upper half, kernel space + asm volatile("msr ttbr1_el1, %0" + : + : "r"((unsigned long) &_end + TTBR_CNP)); + LOG ("TTBR1 written"); + + // finally, toggle some bits in system control register to enable page translation + asm volatile("dsb ish; isb; mrs %0, sctlr_el1" + : "=r"(r)); + r |= 0xC00800; // set mandatory reserved bits + r &= ~((1 << 25) |// clear EE, little endian translation tables + (1 << 24) |// clear E0E + (1 << 19) |// clear WXN + (1 << 12) |// clear I, no instruction cache + (1 << 4) | // clear SA0 + (1 << 3) | // clear SA + (1 << 2) | // clear C, no cache at all + (1 << 1)); // clear A, no aligment check + r |= (1 << 0); // set M, enable MMU + + LOG ("Read out system control register"); + + asm volatile("msr sctlr_el1, %0; isb" + : + : "r"(r)); + + LOG ("Set SCTLR flags and enable MMU"); +} + +void data_abort_el1 (ptr_t far, ptr_t esr) { + byte_t type = (esr >> 2) & 0b11; + byte_t level = esr & 0b11; + esr &= 0b111111; + + printf ("EL 1 - "); + printf ("FAR_EL1: %p - ", far); + printf ("ESR_EL1: %b\n\r", esr); + + switch (type) { + case 0b00:// Address size fault + printf ("Address size fault during level %ld of table walk on lookup of address %p.\r\n", level, far); + // exit_process (); + break; + case 0b01:// Translation fault + printf ("Translation fault during level %ld of table walk on lookup of address %p.\r\n", level, far); + break; + case 0b10:// Access flag fault + printf ("Access flag fault during level %ld of table walk on lookup of address %p.\r\n", level, far); + // exit_process (); + break; + case 0b11:// Permission fault + printf ("Segmentation fault during level %ld of table walk on lookup of address %p.\r\n", level, far); + // exit_process (); + break; + } +} \ No newline at end of file diff --git a/thorn/src/linker.ld b/thorn/src/linker.ld index b0868c4..69512aa 100644 --- a/thorn/src/linker.ld +++ b/thorn/src/linker.ld @@ -4,9 +4,16 @@ SECTIONS .text.boot : { *(.text.boot) } .text : { *(.text) } .rodata : { *(.rodata) } + PROVIDE(_data = .); .data : { *(.data) } - . = ALIGN(0x8); - bss_begin = .; - .bss : { *(.bss*) } - bss_end = .; -} \ No newline at end of file + .bss (NOLOAD) : { + . = ALIGN(16); + __bss_start = .; + *(.bss .bss.*) + *(COMMON) + __bss_end = .; + } + . = ALIGN(4096); + _end = .; +} +__bss_size = (__bss_end - __bss_start) >> 3; From b0db69aa79abcd4d8c654a60900067e01f7d2858 Mon Sep 17 00:00:00 2001 From: Aaron Alef Date: Wed, 3 Nov 2021 16:33:09 +0100 Subject: [PATCH 10/21] feat(thorn): multiplex print to uart and screen --- thorn/src/kernel/kernel.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/thorn/src/kernel/kernel.c b/thorn/src/kernel/kernel.c index ba50281..832b18a 100644 --- a/thorn/src/kernel/kernel.c +++ b/thorn/src/kernel/kernel.c @@ -16,6 +16,11 @@ #include "kernel/sys.h" #include "kernel/timer.h" +void multiplex_print (void * p, char c) { + printc (c); + uart_send (c); +} + void user_process1 (char * array) { char buf[2] = {0}; while (1) { @@ -84,7 +89,7 @@ void kernel_init (void) { printf ("Error: Invalid Framebuffer received\r\n"); } else { font_set_normal (); - init_printf (0, putc_screen); + init_printf (0, multiplex_print); printf ("Frame buffer: %p\r\n", get_fb ()); printf ("Width resolution: %d\r\n", get_fb_info ()->virtual_width); printf ("Height resolution: %d\r\n", get_fb_info ()->virtual_height); From 6ac7e1b30148c5160abada14a82813bc8b05a1a8 Mon Sep 17 00:00:00 2001 From: Max Streitberger Date: Thu, 4 Nov 2021 12:03:31 +0100 Subject: [PATCH 11/21] feat(mmu): fix data abort el0 --- thorn/include/kernel/arm/sysregs.h | 6 +++-- thorn/include/kernel/mmu.h | 2 +- thorn/src/common/printf.c | 13 ++++++++++ thorn/src/kernel/entry.S | 39 +++++++++++++++++++----------- thorn/src/kernel/mmu.c | 12 ++++----- 5 files changed, 49 insertions(+), 23 deletions(-) diff --git a/thorn/include/kernel/arm/sysregs.h b/thorn/include/kernel/arm/sysregs.h index 98acd8b..ccdda11 100644 --- a/thorn/include/kernel/arm/sysregs.h +++ b/thorn/include/kernel/arm/sysregs.h @@ -43,7 +43,9 @@ // ESR_EL1, Exception Syndrome Register (EL1). Page 2431 of AArch64-Reference-Manual. // *************************************** -#define ESR_ELx_EC_SHIFT 26 -#define ESR_ELx_EC_SVC64 0x15 +#define ESR_ELx_EC_SHIFT 26 +#define ESR_ELx_EC_SVC64 0x15 +#define ESR_ELx_EC_DABT_LOW 0b100100 +#define ESR_ELx_EC_DABT_SAME 0b100101 #endif /*_ROSE_K_A_SYSREGS_H*/ diff --git a/thorn/include/kernel/mmu.h b/thorn/include/kernel/mmu.h index b9537a6..169ac60 100644 --- a/thorn/include/kernel/mmu.h +++ b/thorn/include/kernel/mmu.h @@ -45,7 +45,7 @@ static volatile unsigned int __attribute__ ((aligned (16))) buffer[32]; void init_pages (); void init_mmu (void); -void data_abort_el1 (ptr_t far, ptr_t esr); +void data_abort_el0 (ptr_t far, ptr_t esr); #endif #endif//_ROSE_MMU_H \ No newline at end of file diff --git a/thorn/src/common/printf.c b/thorn/src/common/printf.c index 059ee24..80549a9 100644 --- a/thorn/src/common/printf.c +++ b/thorn/src/common/printf.c @@ -206,6 +206,19 @@ void tfp_format (void * putp, putcf putf, char * fmt, va_list va) { unsigned int), 16, (ch == 'P'), bf); putchw (putp, putf, w, lz, bf); break; + case 'b': + case 'B': + putf (putp, '0'); + putf (putp, 'b'); +#ifdef PRINTF_LONG_SUPPORT + if (lng) + uli2a (va_arg (va, unsigned long int), 2, (ch == 'B'), bf); + else +#endif + ui2a (va_arg (va, + unsigned int), 2, (ch == 'B'), bf); + putchw (putp, putf, w, lz, bf); + break; case '%': putf (putp, ch); default: diff --git a/thorn/src/kernel/entry.S b/thorn/src/kernel/entry.S index 4f44a25..950d6ea 100644 --- a/thorn/src/kernel/entry.S +++ b/thorn/src/kernel/entry.S @@ -1,6 +1,7 @@ #include "kernel/arm/sysregs.h" #include "kernel/entry.h" #include "kernel/sys.h" +#include "kernel/mmu.h" .macro handle_invalid_entry el, type kernel_entry \el @@ -8,7 +9,7 @@ mrs x1, esr_el1 mrs x2, elr_el1 bl show_invalid_entry_message - b err_hang + b exit_process .endm .macro ventry label @@ -156,38 +157,48 @@ el0_irq: el0_sync: kernel_entry 0 - mrs x25, esr_el1 // read the syndrome register - lsr x24, x25, #ESR_ELx_EC_SHIFT // exception class - cmp x24, #ESR_ELx_EC_SVC64 // SVC in 64-bit state + mrs x25, esr_el1 // read the syndrome register + lsr x24, x25, #ESR_ELx_EC_SHIFT // exception class + cmp x24, #ESR_ELx_EC_SVC64 // SVC in 64-bit state b.eq el0_svc + cmp x24, #ESR_ELx_EC_DABT_LOW + b.eq el0_da handle_invalid_entry 0, SYNC_ERROR -sc_nr .req x25 // number of system calls -scno .req x26 // syscall number -stbl .req x27 // syscall table pointer +sc_nr .req x25 // number of system calls +scno .req x26 // syscall number +stbl .req x27 // syscall table pointer el0_svc: - adr stbl, sys_call_table // load syscall table pointer - uxtw scno, w8 // syscall number in w8 + adr stbl, sys_call_table // load syscall table pointer + uxtw scno, w8 // syscall number in w8 mov sc_nr, #__NR_syscalls bl enable_irq cmp scno, sc_nr // check upper syscall limit b.hs ni_sys - ldr x16, [stbl, scno, lsl #3] // address in the syscall table - blr x16 // call sys_* routine + ldr x16, [stbl, scno, lsl #3] // address in the syscall table + blr x16 // call sys_* routine b ret_from_syscall ni_sys: handle_invalid_entry 0, SYSCALL_ERROR ret_from_syscall: bl disable_irq - str x0, [sp, #S_X0] // returned x0 + str x0, [sp, #S_X0] // returned x0 kernel_exit 0 +el0_da: + bl enable_irq + mrs x0, far_el1 + mrs x1, esr_el1 + bl data_abort_el0 + bl disable_irq + eret + .globl ret_from_fork ret_from_fork: bl schedule_tail - cbz x19, ret_to_user // not a kernel thread + cbz x19, ret_to_user // not a kernel thread mov x0, x20 blr x19 ret_to_user: @@ -195,4 +206,4 @@ ret_to_user: kernel_exit 0 .globl err_hang -err_hang: b err_hang +err_hang: b err_hang \ No newline at end of file diff --git a/thorn/src/kernel/mmu.c b/thorn/src/kernel/mmu.c index d500828..49ab379 100644 --- a/thorn/src/kernel/mmu.c +++ b/thorn/src/kernel/mmu.c @@ -129,29 +129,29 @@ void init_mmu () { LOG ("Set SCTLR flags and enable MMU"); } -void data_abort_el1 (ptr_t far, ptr_t esr) { +void data_abort_el0 (ptr_t far, ptr_t esr) { byte_t type = (esr >> 2) & 0b11; byte_t level = esr & 0b11; esr &= 0b111111; - printf ("EL 1 - "); + printf ("EL 0 - "); printf ("FAR_EL1: %p - ", far); printf ("ESR_EL1: %b\n\r", esr); switch (type) { case 0b00:// Address size fault - printf ("Address size fault during level %ld of table walk on lookup of address %p.\r\n", level, far); + printf ("Address size fault during level %u of table walk on lookup of address %p.\r\n", level, far); // exit_process (); break; case 0b01:// Translation fault - printf ("Translation fault during level %ld of table walk on lookup of address %p.\r\n", level, far); + printf ("Translation fault during level %u of table walk on lookup of address %p.\r\n", level, far); break; case 0b10:// Access flag fault - printf ("Access flag fault during level %ld of table walk on lookup of address %p.\r\n", level, far); + printf ("Access flag fault during level %u of table walk on lookup of address %p.\r\n", level, far); // exit_process (); break; case 0b11:// Permission fault - printf ("Segmentation fault during level %ld of table walk on lookup of address %p.\r\n", level, far); + printf ("Permission fault during level %u of table walk on lookup of address %p.\r\n", level, far); // exit_process (); break; } From d074e77f71bdf81125b76646f724ad99273cf6eb Mon Sep 17 00:00:00 2001 From: Max Streitberger Date: Thu, 4 Nov 2021 13:55:00 +0100 Subject: [PATCH 12/21] feat(mmu): WIP --- bulb/Makefile | 124 ---------- bulb/include/common/debug.h | 16 -- bulb/include/common/font.h | 42 ---- bulb/include/common/gpu.h | 57 ----- bulb/include/common/logging.h | 27 --- bulb/include/common/printf.h | 107 --------- bulb/include/common/screen.h | 20 -- bulb/include/common/status_led.h | 24 -- bulb/include/common/stdbool.h | 10 - bulb/include/common/stddef.h | 10 - bulb/include/common/utils.h | 12 - bulb/include/kernel/arm/sysregs.h | 51 ---- bulb/include/kernel/entry.h | 35 --- bulb/include/kernel/irq.h | 23 -- bulb/include/kernel/mailbox.h | 40 ---- bulb/include/kernel/mini_uart.h | 33 --- bulb/include/kernel/mm.h | 33 --- bulb/include/kernel/mmu.h | 51 ---- bulb/include/kernel/peripherals/base.h | 6 - bulb/include/kernel/peripherals/gpio.h | 12 - bulb/include/kernel/peripherals/gpu.h | 10 - bulb/include/kernel/peripherals/irq.h | 37 --- bulb/include/kernel/peripherals/mailbox.h | 19 -- bulb/include/kernel/peripherals/mini_uart.h | 25 -- bulb/include/kernel/peripherals/power.h | 21 -- bulb/include/kernel/peripherals/timer.h | 19 -- bulb/include/kernel/power.h | 14 -- bulb/include/kernel/timer.h | 8 - bulb/src/common/debug.c | 29 --- bulb/src/common/font.c | 203 ---------------- bulb/src/common/gpu.c | 137 ----------- bulb/src/common/printf.c | 243 -------------------- bulb/src/common/screen.c | 14 -- bulb/src/common/status_led.c | 55 ----- bulb/src/common/utils.S | 21 -- bulb/src/config.txt | 2 - bulb/src/kernel/boot.S | 52 ----- bulb/src/kernel/entry.S | 181 --------------- bulb/src/kernel/irq.S | 15 -- bulb/src/kernel/irq.c | 51 ---- bulb/src/kernel/kernel.c | 64 ------ bulb/src/kernel/mailbox.c | 52 ----- bulb/src/kernel/mini_uart.c | 87 ------- bulb/src/kernel/mm.S | 14 -- bulb/src/kernel/mm.c | 19 -- bulb/src/kernel/mmu.c | 175 -------------- bulb/src/kernel/power.c | 19 -- bulb/src/kernel/timer.c | 23 -- bulb/src/linker.ld | 19 -- thorn/include/common/utils.h | 4 + thorn/include/kernel/sched.h | 21 +- thorn/src/common/utils.S | 17 ++ thorn/src/kernel/entry.S | 7 +- thorn/src/kernel/fork.c | 12 +- thorn/src/kernel/irq.c | 2 +- thorn/src/kernel/kernel.c | 2 +- thorn/src/kernel/sched.c | 14 +- 57 files changed, 61 insertions(+), 2379 deletions(-) delete mode 100644 bulb/Makefile delete mode 100644 bulb/include/common/debug.h delete mode 100644 bulb/include/common/font.h delete mode 100644 bulb/include/common/gpu.h delete mode 100644 bulb/include/common/logging.h delete mode 100644 bulb/include/common/printf.h delete mode 100644 bulb/include/common/screen.h delete mode 100644 bulb/include/common/status_led.h delete mode 100644 bulb/include/common/stdbool.h delete mode 100644 bulb/include/common/stddef.h delete mode 100644 bulb/include/common/utils.h delete mode 100644 bulb/include/kernel/arm/sysregs.h delete mode 100644 bulb/include/kernel/entry.h delete mode 100644 bulb/include/kernel/irq.h delete mode 100644 bulb/include/kernel/mailbox.h delete mode 100644 bulb/include/kernel/mini_uart.h delete mode 100644 bulb/include/kernel/mm.h delete mode 100644 bulb/include/kernel/mmu.h delete mode 100644 bulb/include/kernel/peripherals/base.h delete mode 100644 bulb/include/kernel/peripherals/gpio.h delete mode 100644 bulb/include/kernel/peripherals/gpu.h delete mode 100644 bulb/include/kernel/peripherals/irq.h delete mode 100644 bulb/include/kernel/peripherals/mailbox.h delete mode 100644 bulb/include/kernel/peripherals/mini_uart.h delete mode 100644 bulb/include/kernel/peripherals/power.h delete mode 100644 bulb/include/kernel/peripherals/timer.h delete mode 100644 bulb/include/kernel/power.h delete mode 100644 bulb/include/kernel/timer.h delete mode 100644 bulb/src/common/debug.c delete mode 100644 bulb/src/common/font.c delete mode 100644 bulb/src/common/gpu.c delete mode 100644 bulb/src/common/printf.c delete mode 100644 bulb/src/common/screen.c delete mode 100644 bulb/src/common/status_led.c delete mode 100644 bulb/src/common/utils.S delete mode 100644 bulb/src/config.txt delete mode 100644 bulb/src/kernel/boot.S delete mode 100644 bulb/src/kernel/entry.S delete mode 100644 bulb/src/kernel/irq.S delete mode 100644 bulb/src/kernel/irq.c delete mode 100644 bulb/src/kernel/kernel.c delete mode 100644 bulb/src/kernel/mailbox.c delete mode 100644 bulb/src/kernel/mini_uart.c delete mode 100644 bulb/src/kernel/mm.S delete mode 100644 bulb/src/kernel/mm.c delete mode 100644 bulb/src/kernel/mmu.c delete mode 100644 bulb/src/kernel/power.c delete mode 100644 bulb/src/kernel/timer.c delete mode 100644 bulb/src/linker.ld diff --git a/bulb/Makefile b/bulb/Makefile deleted file mode 100644 index e510523..0000000 --- a/bulb/Makefile +++ /dev/null @@ -1,124 +0,0 @@ -# | Makefile for the Rose project (github.com/anarchuser/rose) -# | Merged from https://jsandler18.github.io/ and https://github.com/s-matyukevich/raspberry-pi-os - -# Cross-compiler -ARMGNU ?= aarch64-none-elf - -# Resolve Mac / linux issues -HOST_OS = $(shell uname -s) - -# Build target -IMAGE_NAME = $(shell basename `pwd`) - -# Options for C, Asembly, and the linker, respectively -COPS = -Wall -nostdlib -nostartfiles -ffreestanding -Iinclude -mgeneral-regs-only -ASMOPS = -Iinclude -LOPS = -ffreestanding -nostdlib - -# Mount point and boot partition -MNT = $(MNT_$(HOST_OS)) -MNT_Linux = ../mnt -MNT_Darwin = /Volumes/boot - -# Serial connection config -BAUD_RATE = 115200 -SERIAL_PORT = $(SERIAL_PORT_$(HOST_OS)) -SERIAL_PORT_Linux = /dev/$(shell ls /dev | grep ttyUSB | head -n 2 | tail -n 1) -SERIAL_PORT_Darwin = /dev/$(shell ls /dev | grep usbserial | head -n 2 | tail -n 1) - -# Directories for built files, source files (kernel and common) and header files (include) -BUILD = build -SRC = src -KERNEL = kernel -COMMON = common -INCLUDE = include - -# Assemble lists of corresponding source files for assembly, kernel and common -SRC_KERNEL = $(wildcard $(SRC)/$(KERNEL)/*.c) -ASM_KERNEL = $(wildcard $(SRC)/$(KERNEL)/*.S) -SRC_COMMON = $(wildcard $(SRC)/$(COMMON)/*.c) -ASM_COMMON = $(wildcard $(SRC)/$(COMMON)/*.S) - -# Assemble list of compiled objects, correspondingly -OBJECTS = $(patsubst $(SRC)/$(KERNEL)/%.c, $(BUILD)/$(SRC)/$(KERNEL)/%_c.o, $(SRC_KERNEL)) -OBJECTS += $(patsubst $(SRC)/$(KERNEL)/%.S, $(BUILD)/$(SRC)/$(KERNEL)/%_S.o, $(ASM_KERNEL)) -OBJECTS += $(patsubst $(SRC)/$(COMMON)/%.c, $(BUILD)/$(SRC)/$(COMMON)/%_c.o, $(SRC_COMMON)) -OBJECTS += $(patsubst $(SRC)/$(COMMON)/%.S, $(BUILD)/$(SRC)/$(COMMON)/%_S.o, $(ASM_COMMON)) - -# Ensure make still works if someone creates a file named like follows: -.PHONY: build clean flash flash-Linux flash-Darwin emulate reboot poweroff send resend - -# Default target (invoked by `make` or `make build`). -build: $(IMAGE_NAME).img - -# Build kernel executable and linkable file where we can extract the kernel from -$(IMAGE_NAME).elf: $(OBJECTS) $(SRC)/linker.ld - $(ARMGNU)-ld -T $(SRC)/linker.ld -o $(BUILD)/$(IMAGE_NAME).elf $(OBJECTS) - -# Build actual kernel image -$(IMAGE_NAME).img: $(SRC)/linker.ld $(OBJECTS) $(IMAGE_NAME).elf - $(ARMGNU)-objcopy $(BUILD)/$(IMAGE_NAME).elf -O binary $(IMAGE_NAME).img - -# All kernel source targets -$(BUILD)/$(SRC)/$(KERNEL)/%_c.o: $(SRC)/$(KERNEL)/%.c - mkdir -p $(@D) - $(ARMGNU)-gcc $(COPS) -MMD -c $< -o $@ - -# All assembly source targets -$(BUILD)/$(SRC)/$(KERNEL)/%_S.o: $(SRC)/$(KERNEL)/%.S - mkdir -p $(@D) - $(ARMGNU)-gcc $(ASMOPS) -MMD -c $< -o $@ - -# All common source targets -$(BUILD)/$(SRC)/$(COMMON)/%_c.o: $(SRC)/$(COMMON)/%.c - mkdir -p $(@D) - $(ARMGNU)-gcc $(COPS) -MMD -c $< -o $@ - -# All assembly source targets -$(BUILD)/$(SRC)/$(COMMON)/%_S.o: $(SRC)/$(COMMON)/%.S - mkdir -p $(@D) - $(ARMGNU)-gcc $(ASMOPS) -MMD -c $< -o $@ - -# Compile lists with the dependencies between objects -DEP_FILES = $(OBJECTS:%.o=%.d) - -include $(DEP_FILES) - -# Remove kernel and build directory -clean: - rm -rf $(BUILD) *.img - -# Mount boot partition of SD card onto set mount point to copy image onto it -flash: flash-$(HOST_OS) - -flash-Linux: $(IMAGE_NAME).img - mkdir -p $(MNT) - mount $(MNT) - cp $(IMAGE_NAME).img $(MNT)/kernel8.img - cp $(SRC)/config.txt $(MNT) - sync - sleep 1 - umount $(MNT) - -flash-Darwin: $(IMAGE_NAME).img - cp $(IMAGE_NAME).img $(MNT)/kernel8.img - cp $(SRC)/config.txt $(MNT) - sync - diskutil unmount $(MNT) - -resend: reboot send - -send: $(IMAGE_NAME).img - printf "0: %.8x" $(shell wc -c < $(IMAGE_NAME).img) | xxd -r -g0 > $(SERIAL_PORT) - cat $(IMAGE_NAME).img > $(SERIAL_PORT) - -# Run on qemu -emulate: $(IMAGE_NAME).img - qemu-img resize $(IMAGE_NAME).img -f raw 4294967296 - qemu-system-aarch64 -cpu cortex-a72 -machine type=raspi3 -m 1024 -kernel $(IMAGE_NAME).img -nographic -serial null -chardev stdio,id=uart1 -serial chardev:uart1 -monitor none - -poweroff: - $(MAKE) -C .. poweroff - -reboot: - $(MAKE) -C .. reboot - diff --git a/bulb/include/common/debug.h b/bulb/include/common/debug.h deleted file mode 100644 index 99e2ec3..0000000 --- a/bulb/include/common/debug.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _ROSE_C_DEBUG_H -#define _ROSE_DEBUG_H - -#include "common/logging.h" -#include "common/printf.h" -#include "common/stddef.h" - -#define CHECKPOINT LOG ("Checkpoint"); - -void print_hex (unsigned char dec); - -void hex_dump (byte_t * array); - -void int_dump (unsigned int * array); - -#endif//_ROSE_C_DEBUG_H \ No newline at end of file diff --git a/bulb/include/common/font.h b/bulb/include/common/font.h deleted file mode 100644 index 0791dde..0000000 --- a/bulb/include/common/font.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef _ROSE_C_FONT_H -#define _ROSE_C_FONT_H - -#define FONT_SIZE 8 -#define FONT_FACTOR 4 -#define FONT_REAL_WIDTH (FONT_SIZE * FONT_FACTOR) - -// Spacing between lines in pixels -#define FONT_SPACING 4 -#define FONT_REAL_HEIGHT (FONT_REAL_WIDTH + FONT_SPACING) - -// Width of horizontal tabs in characters -#define FONT_TAB_SIZE 4 -#define FONT_TAB_REAL_WIDTH (FONT_TAB_SIZE * FONT_REAL_WIDTH) - -// If this is defined, scrollback is used -#define FONT_SCROLLBACK -// Scroll by this amount at the same time. High = fast, low = fancy -#define FONT_SB_LINES 1 - -#include "common/gpu.h" -#include "common/screen.h" -#include "kernel/mm.h" - -static point_t cursor = {0, 0}; - -static volatile color_t font_bg = {0x00, 0x00, 0x00, 0x00}; -static volatile color_t font_normal_fg = {0xC0, 0xC0, 0xC0, 0x00}; -static volatile color_t font_error_fg = {0x00, 0x00, 0xC0, 0x00}; -static volatile color_t font_fg; - -const unsigned long long int * font (int c); - -void printc (char c); -void printc_location (point_t point, char c); - -void putc_screen (void * p, char c); - -void font_set_normal (void); -void font_set_error (void); - -#endif diff --git a/bulb/include/common/gpu.h b/bulb/include/common/gpu.h deleted file mode 100644 index 1237103..0000000 --- a/bulb/include/common/gpu.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef _ROSE_C_GPU_H -#define _ROSE_C_GPU_H - -#include "common/printf.h" - -#include "common/stdbool.h" -#include "common/stddef.h" -#include "kernel/mailbox.h" -#include "kernel/mm.h" -#include "kernel/peripherals/gpu.h" - -// Reference: -// https://jsandler18.github.io/extra/prop-channel.html - -// Uncomment to override physical / virtual screen size with the values defined below -#define GPU_OVERRIDE_PHYSICAL_SCREEN - -#define GPU_SCREEN_WIDTH 1920// Width used if Override is enabled -#define GPU_SCREEN_HEIGHT 1080// Height used if Override is enabled - -#define GPU_VIRTUAL_WIDTH GPU_SCREEN_WIDTH -#define GPU_VIRTUAL_HEIGHT GPU_SCREEN_HEIGHT - -#define GPU_COLOUR_DEPTH 32 - -#define VC_SDRAM_OFFSET 0x3FFFFFFF - -typedef struct { - byte_t blue; - byte_t green; - byte_t red; - byte_t alpha; -} color_t; - -typedef struct { - color_t * fb; - unsigned int fb_size; - short virtual_width; - short virtual_height; - short pitch; - short colour_depth; -} fb_info_t; - -static volatile unsigned int __attribute__ ((aligned (16))) gpu_msg_buffer[128]; - -static fb_info_t fb_info; - -bool init_gpu (void); - -color_t * get_fb (void); - -fb_info_t const * get_fb_info (void); - -bool blank_screen (bool blank); -bool toggle_blank_screen (void); - -#endif//_ROSE_C_GPU_H \ No newline at end of file diff --git a/bulb/include/common/logging.h b/bulb/include/common/logging.h deleted file mode 100644 index 6203d6b..0000000 --- a/bulb/include/common/logging.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _ROSE_C_LOGGING_H -#define _ROSE_C_LOGGING_H - -#include "common/printf.h" - -#define LOG(msg) \ - do { \ - static int __counter__ = 0; \ - printf (__FILE__ ":%d:[%d] %s\r\n", __LINE__, __counter__++, msg); \ - } while (0) - -#define ERROR(msg) \ - do { \ - static int __counter__ = 0; \ - font_set_error (); \ - printf (__FILE__ ":%d:[%d] %s\r\n", __LINE__, __counter__++, msg); \ - font_set_normal (); \ - } while (0) - -#define ASSERT(expr) \ - do { \ - if (! (expr)) \ - LOG ("Assertion failed"); \ - } while (0) - - -#endif /*_ROSE_C_LOGGING_H*/ diff --git a/bulb/include/common/printf.h b/bulb/include/common/printf.h deleted file mode 100644 index 382087b..0000000 --- a/bulb/include/common/printf.h +++ /dev/null @@ -1,107 +0,0 @@ -/* -File: printf.h - -Copyright (C) 2004 Kustaa Nyholm - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -This library is really just two files: 'printf.h' and 'printf.c'. - -They provide a simple and small (+200 loc) printf functionality to -be used in embedded systems. - -I've found them so usefull in debugging that I do not bother with a -debugger at all. - -They are distributed in source form, so to use them, just compile them -into your project. - -Two printf variants are provided: printf and sprintf. - -The formats supported by this implementation are: 'd' 'u' 'c' 's' 'x' 'X'. - -Zero padding and field width are also supported. - -If the library is compiled with 'PRINTF_SUPPORT_LONG' defined then the -long specifier is also -supported. Note that this will pull in some long math routines (pun intended!) -and thus make your executable noticably longer. - -The memory foot print of course depends on the target cpu, compiler and -compiler options, but a rough guestimate (based on a H8S target) is about -1.4 kB for code and some twenty 'int's and 'char's, say 60 bytes of stack space. -Not too bad. Your milage may vary. By hacking the source code you can -get rid of some hunred bytes, I'm sure, but personally I feel the balance of -functionality and flexibility versus code size is close to optimal for -many embedded systems. - -To use the printf you need to supply your own character output function, -something like : - - void putc ( void* p, char c) - { - while (!SERIAL_PORT_EMPTY) ; - SERIAL_PORT_TX_REGISTER = c; - } - -Before you can call printf you need to initialize it to use your -character output function with something like: - - init_printf(NULL,putc); - -Notice the 'NULL' in 'init_printf' and the parameter 'void* p' in 'putc', -the NULL (or any pointer) you pass into the 'init_printf' will eventually be -passed to your 'putc' routine. This allows you to pass some storage space (or -anything really) to the character output function, if necessary. -This is not often needed but it was implemented like that because it made -implementing the sprintf function so neat (look at the source code). - -The code is re-entrant, except for the 'init_printf' function, so it -is safe to call it from interupts too, although this may result in mixed output. -If you rely on re-entrancy, take care that your 'putc' function is re-entrant! - -The printf and sprintf functions are actually macros that translate to -'tfp_printf' and 'tfp_sprintf'. This makes it possible -to use them along with 'stdio.h' printf's in a single source file. -You just need to undef the names before you include the 'stdio.h'. -Note that these are not function like macros, so if you have variables -or struct members with these names, things will explode in your face. -Without variadic macros this is the best we can do to wrap these -fucnction. If it is a problem just give up the macros and use the -functions directly or rename them. - -For further details see source code. - -regs Kusti, 23.10.2004 -*/ - - -#ifndef __TFP_PRINTF__ -#define __TFP_PRINTF__ - -#include - -void init_printf (void * putp, void (*putf) (void *, char)); - -void tfp_printf (char * fmt, ...); - -void tfp_sprintf (char * s, char * fmt, ...); - -void tfp_format (void * putp, void (*putf) (void *, char), char * fmt, va_list va); - -#define printf tfp_printf -#define sprintf tfp_sprintf - -#endif diff --git a/bulb/include/common/screen.h b/bulb/include/common/screen.h deleted file mode 100644 index 3e969d7..0000000 --- a/bulb/include/common/screen.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef _ROSE_C_SCREEN_H -#define _ROSE_C_SCREEN_H -#include "common/gpu.h" - -typedef struct { - unsigned int x, y; -} point_t; - -// point_t point (unsigned int x, unsigned int y); -#define POINT(x, y) \ - (point_t) { \ - x, y \ - } - -void drawpx (point_t p, color_t color); - -short get_max_width (); -short get_max_height (); - -#endif//_ROSE_C_SCREEN_H diff --git a/bulb/include/common/status_led.h b/bulb/include/common/status_led.h deleted file mode 100644 index 0a7096e..0000000 --- a/bulb/include/common/status_led.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef _ROSE_C_STATUS_LED_H -#define _ROSE_C_STATUS_LED_H - -#include "common/stdbool.h" -#include "kernel/mailbox.h" - -// Following https://github.com/mathlizee/Rasperry-Pi-3 - -enum { - STATUS_LED = 42, - POWER_LED = 130 -}; - -static volatile unsigned int __attribute__ ((aligned (16))) led_msg_buffer[32]; - - -bool get_led (int pin); - -void set_led (bool status, int pin); - -bool toggle_led (int pin); - - -#endif//_ROSE_C_STATUS_LED_H diff --git a/bulb/include/common/stdbool.h b/bulb/include/common/stdbool.h deleted file mode 100644 index 2c03282..0000000 --- a/bulb/include/common/stdbool.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _ROSE_C_BOOL_H -#define _ROSE_C_BOOL_H - -#define true 1 -#define false 0 -#define __bool_true_false_are_defined - -typedef char bool; - -#endif /*_ROSE_C_BOOL_H*/ diff --git a/bulb/include/common/stddef.h b/bulb/include/common/stddef.h deleted file mode 100644 index 8d9feaa..0000000 --- a/bulb/include/common/stddef.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _ROSE_C_STDDEF_H -#define _ROSE_C_STDDEF_H - -#define NULL 0 - -#define ptr_t unsigned long - -#define byte_t unsigned char - -#endif//_ROSE_C_STDDEF_H \ No newline at end of file diff --git a/bulb/include/common/utils.h b/bulb/include/common/utils.h deleted file mode 100644 index 29b53a1..0000000 --- a/bulb/include/common/utils.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _ROSE_C_BOOT_H -#define _ROSE_C_BOOT_H - -extern void delay (unsigned long); - -extern void put32 (unsigned long, unsigned int); - -extern unsigned int get32 (unsigned long); - -extern int get_el (void); - -#endif /*_ROSE_C_BOOT_H */ diff --git a/bulb/include/kernel/arm/sysregs.h b/bulb/include/kernel/arm/sysregs.h deleted file mode 100644 index ccdda11..0000000 --- a/bulb/include/kernel/arm/sysregs.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _ROSE_K_A_SYSREGS_H -#define _ROSE_K_A_SYSREGS_H - -// *************************************** -// SCTLR_EL1, System Control Register (EL1), 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) - -// *************************************** -// HCR_EL2, Hypervisor Configuration Register (EL2), Page 2487 of AArch64-Reference-Manual. -// *************************************** - -#define HCR_RW (1 << 31) -#define HCR_VALUE HCR_RW - -// *************************************** -// SCR_EL3, Secure Configuration Register (EL3), 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) - -// *************************************** -// SPSR_EL3, Saved Program Status Register (EL3) 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) - -// *************************************** -// ESR_EL1, Exception Syndrome Register (EL1). Page 2431 of AArch64-Reference-Manual. -// *************************************** - -#define ESR_ELx_EC_SHIFT 26 -#define ESR_ELx_EC_SVC64 0x15 -#define ESR_ELx_EC_DABT_LOW 0b100100 -#define ESR_ELx_EC_DABT_SAME 0b100101 - -#endif /*_ROSE_K_A_SYSREGS_H*/ diff --git a/bulb/include/kernel/entry.h b/bulb/include/kernel/entry.h deleted file mode 100644 index 0152f82..0000000 --- a/bulb/include/kernel/entry.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef _ROSE_K_ENTRY_H -#define _ROSE_K_ENTRY_H - -#define S_FRAME_SIZE 272// size of all saved registers -#define S_X0 0 // offset of x0 register in saved stack frame - -#define SYNC_INVALID_EL1t 0 -#define IRQ_INVALID_EL1t 1 -#define FIQ_INVALID_EL1t 2 -#define ERROR_INVALID_EL1t 3 - -#define SYNC_INVALID_EL1h 4 -#define IRQ_INVALID_EL1h 5 -#define FIQ_INVALID_EL1h 6 -#define ERROR_INVALID_EL1h 7 - -#define SYNC_INVALID_EL0_64 8 -#define IRQ_INVALID_EL0_64 9 -#define FIQ_INVALID_EL0_64 10 -#define ERROR_INVALID_EL0_64 11 - -#define SYNC_INVALID_EL0_32 12 -#define IRQ_INVALID_EL0_32 13 -#define FIQ_INVALID_EL0_32 14 -#define ERROR_INVALID_EL0_32 15 - -#define SYNC_ERROR 16 -#define SYSCALL_ERROR 17 - -#ifndef __ASSEMBLER__ - -void ret_from_fork (void); - -#endif -#endif diff --git a/bulb/include/kernel/irq.h b/bulb/include/kernel/irq.h deleted file mode 100644 index 9221696..0000000 --- a/bulb/include/kernel/irq.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef _ROSE_K_IRQ_H -#define _ROSE_K_IRQ_H - -#include "common/printf.h" -#include "common/stddef.h" -#include "common/utils.h" -#include "kernel/arm/sysregs.h" -#include "kernel/entry.h" -#include "kernel/peripherals/irq.h" - -#include "kernel/mini_uart.h" - -void enable_interrupt_controller (void); - -void show_invalid_entry_message (int type, ptr_t esr, ptr_t address); - -void irq_vector_init (void); - -void enable_irq (void); - -void disable_irq (void); - -#endif /*_ROSE_K_IRQ_H */ diff --git a/bulb/include/kernel/mailbox.h b/bulb/include/kernel/mailbox.h deleted file mode 100644 index b4f6dd8..0000000 --- a/bulb/include/kernel/mailbox.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef _ROSE_K_MAILBOX_H -#define _ROSE_K_MAILBOX_H - -#include "common/stdbool.h" -#include "common/stddef.h" -#include "common/utils.h" -#include "kernel/mm.h" -#include "kernel/peripherals/mailbox.h" - -#include "common/debug.h" -#include "common/logging.h" - -#define DUMP_BUFFER false - -// Documentation: -// https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface - -typedef enum { - POWER = 0, - FRAMEBUFFER, - VIRTUAL_UART, - VCHIQ, - LEDS, - BUTTONS, - TOUCH_SCREEN, - RESERVED, - PROPERTY_ARM_VC,// Request from ARM for response by VC - PROPERTY_VC_ARM // Request from VC for response by ARM (Currently not in use) -} channel_t; - - -typedef struct { - unsigned int data : 28;// most significant bits contain shared memory address - channel_t channel : 4; // least four significant bits contain channel -} mbox_message_t; - -// Send message and check responses -bool mailbox_request (volatile unsigned int * data_ptr, channel_t channel); - -#endif//_ROSE_K_MAILBOX_H diff --git a/bulb/include/kernel/mini_uart.h b/bulb/include/kernel/mini_uart.h deleted file mode 100644 index 46499cf..0000000 --- a/bulb/include/kernel/mini_uart.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef _ROSE_K_UART_H -#ifndef _ROSE_K_MINI_UART_H -#define _ROSE_K_MINI_UART_H - -#include "common/gpu.h" -#include "common/stdbool.h" -#include "common/utils.h" -#include "kernel/peripherals/gpio.h" -#include "kernel/peripherals/mini_uart.h" -//#include "kernel/power.h" - -void mini_uart_init (void); - -char mini_uart_recv (void); - -void mini_uart_send (char c); - -void mini_uart_send_string (char * str); - -void handle_mini_uart_irq (void); - -// This function is required by printf function -void mini_putc (void * p, char c); - -#define uart_init mini_uart_init -#define uart_recv mini_uart_recv -#define uart_send mini_uart_send -#define uart_send_string mini_uart_send_string - -#define putc mini_putc - -#endif /*_ROSE_K_MINI_UART_H */ -#endif /*_ROSE_K_UART_H */ diff --git a/bulb/include/kernel/mm.h b/bulb/include/kernel/mm.h deleted file mode 100644 index 7acc222..0000000 --- a/bulb/include/kernel/mm.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef _ROSE_K_MM_H -#define _ROSE_K_MM_H - -#include "common/stddef.h" -#include "peripherals/base.h" - -#define PAGE_SHIFT 12 -#define TABLE_SHIFT 9 -#define SECTION_SHIFT (PAGE_SHIFT + TABLE_SHIFT) - -#define PAGE_SIZE (1 << PAGE_SHIFT) -#define SECTION_SIZE (1 << SECTION_SHIFT) - -#define LOW_MEMORY (2 * SECTION_SIZE) -#define HIGH_MEMORY 0x70000000 - -#define PAGING_MEMORY (HIGH_MEMORY - LOW_MEMORY) -#define PAGING_PAGES (PAGING_MEMORY / PAGE_SIZE) - -#ifndef __ASSEMBLER__ - -extern char _start; -#define KERNEL_START ((ptr_t) &_start) - -ptr_t get_free_page (); - -void free_page (ptr_t p); - -void memzero (ptr_t src, ptr_t n); - -#endif - -#endif /*_ROSE_K_MM_H */ diff --git a/bulb/include/kernel/mmu.h b/bulb/include/kernel/mmu.h deleted file mode 100644 index b9537a6..0000000 --- a/bulb/include/kernel/mmu.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _ROSE_MMU_H -#define _ROSE_MMU_H - -#ifndef __ASSEMBLER__ - -// Implementation taken from -// https://github.com/bztsrc/raspi3-tutorial/blob/master/10_virtualmemory/mmu.c - -#include "common/font.h" -#include "common/logging.h" -#include "common/status_led.h" -#include "kernel/mini_uart.h" -#include "kernel/peripherals/base.h" - -#define PAGESIZE 4096 - -// granularity -#define PT_PAGE 0b11// 4k granule -#define PT_BLOCK 0b01// 2M granule -// accessibility -#define PT_KERNEL (0 << 6) // privileged, supervisor EL1 access only -#define PT_USER (1 << 6) // unprivileged, EL0 access allowed -#define PT_RW (0 << 7) // read-write -#define PT_RO (1 << 7) // read-only -#define PT_AF (1 << 10) // accessed flag -#define PT_NX (1UL << 54)// no execute -// shareability -#define PT_OSH (2 << 8)// outter shareable -#define PT_ISH (3 << 8)// inner shareable -// defined in MAIR register -#define PT_MEM (0 << 2)// normal memory -#define PT_DEV (1 << 2)// device MMIO -#define PT_NC (2 << 2)// non-cachable - -#define TTBR_CNP 1 - -#define RAM_IN_GB 8 - -// get addresses from linker -extern volatile unsigned char _data; -extern volatile unsigned char _end; - -static volatile unsigned int __attribute__ ((aligned (16))) buffer[32]; - -void init_pages (); -void init_mmu (void); - -void data_abort_el1 (ptr_t far, ptr_t esr); - -#endif -#endif//_ROSE_MMU_H \ No newline at end of file diff --git a/bulb/include/kernel/peripherals/base.h b/bulb/include/kernel/peripherals/base.h deleted file mode 100644 index 12f55d7..0000000 --- a/bulb/include/kernel/peripherals/base.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ROSE_K_P_BASE_H -#define _ROSE_K_P_BASE_H - -#define PBASE 0xFE000000 - -#endif /*_ROSE_K_P_BASE_H */ diff --git a/bulb/include/kernel/peripherals/gpio.h b/bulb/include/kernel/peripherals/gpio.h deleted file mode 100644 index 8354caf..0000000 --- a/bulb/include/kernel/peripherals/gpio.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _ROSE_K_P_GPIO_H -#define _ROSE_K_P_GPIO_H - -#include "kernel/peripherals/base.h" - -#define GPFSEL1 (PBASE + 0x00200004) -#define GPSET0 (PBASE + 0x0020001C) -#define GPCLR0 (PBASE + 0x00200028) -#define GPPUD (PBASE + 0x00200094) -#define GPPUDCLK0 (PBASE + 0x00200098) - -#endif /*_ROSE_K_P_GPIO_H */ diff --git a/bulb/include/kernel/peripherals/gpu.h b/bulb/include/kernel/peripherals/gpu.h deleted file mode 100644 index 2408fba..0000000 --- a/bulb/include/kernel/peripherals/gpu.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _ROSE_K_P_GPU_H -#define _ROSE_K_P_GPU_H - -#define GPU_REQUEST_FRAMEBUFFER 0x40001 -#define GPU_BLANK_SCREEN 0x40002 -#define GPU_SET_SCREEN_SIZE 0x48003 -#define GPU_SET_VIRTUAL_SIZE 0x48004 -#define GPU_SET_COLOUR_DEPTH 0x48005 - -#endif//_ROSE_K_P_GPU_H \ No newline at end of file diff --git a/bulb/include/kernel/peripherals/irq.h b/bulb/include/kernel/peripherals/irq.h deleted file mode 100644 index 9900292..0000000 --- a/bulb/include/kernel/peripherals/irq.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef _ROSE_K_P_IRQ_H -#define _ROSE_K_P_IRQ_H - -#include "kernel/peripherals/base.h" - -#define GIC_BASE 0xFF840000 -#define GICD_DIST_BASE (GIC_BASE + 0x00001000) -#define GICC_CPU_BASE (GIC_BASE + 0x00002000) - -#define GICD_ENABLE_IRQ_BASE (GICD_DIST_BASE + 0x00000100) - -#define GICC_IAR (GICC_CPU_BASE + 0x0000000C) -#define GICC_EOIR (GICC_CPU_BASE + 0x00000010) - -#define GIC_IRQ_TARGET_BASE (GICD_DIST_BASE + 0x00000800) - -//VC (=VideoCore) starts at 96 -#define SYSTEM_TIMER_IRQ_0 (0x60)//96 -#define SYSTEM_TIMER_IRQ_1 (0x61)//97 -#define SYSTEM_TIMER_IRQ_2 (0x62)//98 -#define SYSTEM_TIMER_IRQ_3 (0x63)//99 - -#define IRQ_BASIC_PENDING (PBASE + 0x0000B200) -#define IRQ_PENDING_1 (PBASE + 0x0000B204) -#define IRQ_PENDING_2 (PBASE + 0x0000B208) -#define FIQ_CONTROL (PBASE + 0x0000B20C) -#define ENABLE_IRQS_1 (PBASE + 0x0000B210) -#define ENABLE_IRQS_2 (PBASE + 0x0000B214) -#define ENABLE_BASIC_IRQS (PBASE + 0x0000B218) -#define DISABLE_IRQS_1 (PBASE + 0x0000B21C) -#define DISABLE_IRQS_2 (PBASE + 0x0000B220) -#define DISABLE_BASIC_IRQS (PBASE + 0x0000B224) - -#define MINI_UART_IRQ (1 << 0) -#define ENABLE_AUX_INT (1 << 29) - -#endif /*_ROSE_K_P_IRQ_H */ diff --git a/bulb/include/kernel/peripherals/mailbox.h b/bulb/include/kernel/peripherals/mailbox.h deleted file mode 100644 index 37f664c..0000000 --- a/bulb/include/kernel/peripherals/mailbox.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _ROSE_K_P_MAILBOX_H -#define _ROSE_K_P_MAILBOX_H - -#include "base.h" - -#define MBOX0 (PBASE + 0xB880)// Read from CPU -#define MBOX1 (PBASE + 0xB840)// Write to CPU - -#define MBOX_READ 0x00 -#define MBOX_STATUS 0x18 -#define MBOX_IRQ 0x1C -#define MBOX_WRITE 0x20 - -#define MBOX_READ_EMPTY (1 << 30) -#define MBOX_WRITE_FULL (1 << 31) - -#define MBOX_SUCCESS 0x80000000 - -#endif//_ROSE_K_P_MAILBOX_H \ No newline at end of file diff --git a/bulb/include/kernel/peripherals/mini_uart.h b/bulb/include/kernel/peripherals/mini_uart.h deleted file mode 100644 index b065deb..0000000 --- a/bulb/include/kernel/peripherals/mini_uart.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef _ROSE_K_P_MINI_UART_H -#define _ROSE_K_P_MINI_UART_H - -#include "base.h" - -#define SYSTEM_CLOCK_FREQ 500000000 -#define BAUD_RATE_REG(target_baudrate) ((SYSTEM_CLOCK_FREQ / target_baudrate / 8) - 1) - -#define AUX_IRQ_REG (PBASE + 0x00215000) -#define AUX_ENABLES (PBASE + 0x00215004) -#define AUX_MU_IO_REG (PBASE + 0x00215040) -#define AUX_MU_IER_REG (PBASE + 0x00215044) -#define AUX_MU_IIR_REG (PBASE + 0x00215048) -#define AUX_MU_LCR_REG (PBASE + 0x0021504C) -#define AUX_MU_MCR_REG (PBASE + 0x00215050) -#define AUX_MU_LSR_REG (PBASE + 0x00215054) -#define AUX_MU_MSR_REG (PBASE + 0x00215058) -#define AUX_MU_SCRATCH (PBASE + 0x0021505C) -#define AUX_MU_CNTL_REG (PBASE + 0x00215060) -#define AUX_MU_STAT_REG (PBASE + 0x00215064) -#define AUX_MU_BAUD_REG (PBASE + 0x00215068) - -#define ENABLE_MU_REC_INT (0xFD) - -#endif /*_ROSE_K_P_MINI_UART_H */ diff --git a/bulb/include/kernel/peripherals/power.h b/bulb/include/kernel/peripherals/power.h deleted file mode 100644 index b02469f..0000000 --- a/bulb/include/kernel/peripherals/power.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _ROSE_K_P_POWER_H -#define _ROSE_K_P_POWER_H - -#include "kernel/peripherals/base.h" - -#define PM_BASE PBASE + 0x100000 - -#define PM_RSTC PM_BASE + 0x1c -#define PM_WDOG PM_BASE + 0x24 - -#define PM_WDOG_RESET 0000000000 -#define PM_PASSWORD 0x5a000000 -#define PM_WDOG_TIME_SET 0x000fffff -#define PM_RSTC_WRCFG_CLR 0xffffffcf -#define PM_RSTC_WRCFG_SET 0x00000030 -#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 -#define PM_RSTC_RESET 0x00000102 - -#endif//_ROSE_K_P_POWER_H - -/* Copyright (C) 2020 Aaron Alef */ \ No newline at end of file diff --git a/bulb/include/kernel/peripherals/timer.h b/bulb/include/kernel/peripherals/timer.h deleted file mode 100644 index ae3bf7f..0000000 --- a/bulb/include/kernel/peripherals/timer.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _ROSE_K_P_TIMER_H -#define _ROSE_K_P_TIMER_H - -#include "kernel/peripherals/base.h" - -#define TIMER_CS (PBASE + 0x00003000) -#define TIMER_CLO (PBASE + 0x00003004) -#define TIMER_CHI (PBASE + 0x00003008) -#define TIMER_C0 (PBASE + 0x0000300C) -#define TIMER_C1 (PBASE + 0x00003010) -#define TIMER_C2 (PBASE + 0x00003014) -#define TIMER_C3 (PBASE + 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 /*_ROSE_K_P_TIMER_H */ diff --git a/bulb/include/kernel/power.h b/bulb/include/kernel/power.h deleted file mode 100644 index 031db9c..0000000 --- a/bulb/include/kernel/power.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _ROSE_K_POWER_H -#define _ROSE_K_POWER_H - -#include "common/stdbool.h" -#include "common/utils.h" -#include "kernel/peripherals/power.h" - -// power off (timeout / 16 in seconds?) -void poweroff (unsigned int timeout, bool block); - -// reboot (timeout / 16 in seconds?) -void reboot (unsigned int timeout, bool block); - -#endif//_ROSE_K_POWER_H \ No newline at end of file diff --git a/bulb/include/kernel/timer.h b/bulb/include/kernel/timer.h deleted file mode 100644 index f5cd0b8..0000000 --- a/bulb/include/kernel/timer.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _ROSE_K_TIMER_H -#define _ROSE_K_TIMER_H - -void timer_init (void); - -void handle_timer_irq (void); - -#endif /*_ROSE_K_TIMER_H */ diff --git a/bulb/src/common/debug.c b/bulb/src/common/debug.c deleted file mode 100644 index 4a65209..0000000 --- a/bulb/src/common/debug.c +++ /dev/null @@ -1,29 +0,0 @@ -#include "common/debug.h" - -void print_hex (unsigned char dec) { - char fst = dec / 16; - char snd = dec % 16; - fst = (fst > 9) ? 'A' + fst - 10 : '0' + fst; - snd = (snd > 9) ? 'A' + snd - 10 : '0' + snd; - printf ("%c%c ", fst, snd); -} - -void hex_dump (byte_t * array) { - for (int i = 0; i < *(unsigned int *) array;) { - i += 4; - for (int j = 1; j <= 4; j++) { - print_hex (array[i - j]); - } - printf (" "); - if (!(i % 32)) - printf ("\r\n"); - } - printf ("\r\n"); -} - -void int_dump (unsigned int * array) { - for (int i = 0; i < *array / 4; i++) { - printf ("%d ", array[i]); - } - printf ("\r\n"); -} diff --git a/bulb/src/common/font.c b/bulb/src/common/font.c deleted file mode 100644 index 8e61da3..0000000 --- a/bulb/src/common/font.c +++ /dev/null @@ -1,203 +0,0 @@ -#include "common/font.h" - -/* From https://github.com/dhepper/font8x8/blob/master/font8x8_block.h */ -const unsigned long long int * font (int c) { - static const char f[128][FONT_SIZE] = { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0000 (nul) - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0001 - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0002 - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0003 - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0004 - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0005 - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0006 - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0007 - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0008 - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0009 - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+000A - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+000B - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+000C - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+000D - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+000E - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+000F - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0010 - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0011 - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0012 - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0013 - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0014 - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0015 - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0016 - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0017 - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0018 - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0019 - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+001A - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+001B - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+001C - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+001D - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+001E - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+001F - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0020 (space) - {0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00},// U+0021 (!) - {0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0022 (") - {0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00},// U+0023 (#) - {0x0C, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x0C, 0x00},// U+0024 ($) - {0x00, 0x63, 0x33, 0x18, 0x0C, 0x66, 0x63, 0x00},// U+0025 (%) - {0x1C, 0x36, 0x1C, 0x6E, 0x3B, 0x33, 0x6E, 0x00},// U+0026 (&) - {0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0027 (') - {0x18, 0x0C, 0x06, 0x06, 0x06, 0x0C, 0x18, 0x00},// U+0028 (() - {0x06, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x06, 0x00},// U+0029 ()) - {0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00},// U+002A (*) - {0x00, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x00, 0x00},// U+002B (+) - {0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x06},// U+002C (,) - {0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00},// U+002D (-) - {0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00},// U+002E (.) - {0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00},// U+002F (/) - {0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00},// U+0030 (0) - {0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00},// U+0031 (1) - {0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00},// U+0032 (2) - {0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00},// U+0033 (3) - {0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00},// U+0034 (4) - {0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00},// U+0035 (5) - {0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00},// U+0036 (6) - {0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00},// U+0037 (7) - {0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00},// U+0038 (8) - {0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00},// U+0039 (9) - {0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x00},// U+003A (:) - {0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x06},// U+003B (//) - {0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x00},// U+003C (<) - {0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x00},// U+003D (=) - {0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00},// U+003E (>) - {0x1E, 0x33, 0x30, 0x18, 0x0C, 0x00, 0x0C, 0x00},// U+003F (?) - {0x3E, 0x63, 0x7B, 0x7B, 0x7B, 0x03, 0x1E, 0x00},// U+0040 (@) - {0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00},// U+0041 (A) - {0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00},// U+0042 (B) - {0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00},// U+0043 (C) - {0x1F, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00},// U+0044 (D) - {0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00},// U+0045 (E) - {0x7F, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x0F, 0x00},// U+0046 (F) - {0x3C, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7C, 0x00},// U+0047 (G) - {0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00},// U+0048 (H) - {0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00},// U+0049 (I) - {0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, 0x00},// U+004A (J) - {0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00},// U+004B (K) - {0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00},// U+004C (L) - {0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00},// U+004D (M) - {0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00},// U+004E (N) - {0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00},// U+004F (O) - {0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00},// U+0050 (P) - {0x1E, 0x33, 0x33, 0x33, 0x3B, 0x1E, 0x38, 0x00},// U+0051 (Q) - {0x3F, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x67, 0x00},// U+0052 (R) - {0x1E, 0x33, 0x07, 0x0E, 0x38, 0x33, 0x1E, 0x00},// U+0053 (S) - {0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00},// U+0054 (T) - {0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x00},// U+0055 (U) - {0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00},// U+0056 (V) - {0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00},// U+0057 (W) - {0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00},// U+0058 (X) - {0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00},// U+0059 (Y) - {0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00},// U+005A (Z) - {0x1E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1E, 0x00},// U+005B ([) - {0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00},// U+005C (\) - {0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x00},// U+005D (]) - {0x08, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00},// U+005E (^) - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF},// U+005F (_) - {0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00},// U+0060 (`) - {0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x6E, 0x00},// U+0061 (a) - {0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3B, 0x00},// U+0062 (b) - {0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00},// U+0063 (c) - {0x38, 0x30, 0x30, 0x3e, 0x33, 0x33, 0x6E, 0x00},// U+0064 (d) - {0x00, 0x00, 0x1E, 0x33, 0x3f, 0x03, 0x1E, 0x00},// U+0065 (e) - {0x1C, 0x36, 0x06, 0x0f, 0x06, 0x06, 0x0F, 0x00},// U+0066 (f) - {0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x1F},// U+0067 (g) - {0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x67, 0x00},// U+0068 (h) - {0x0C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00},// U+0069 (i) - {0x30, 0x00, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E},// U+006A (j) - {0x07, 0x06, 0x66, 0x36, 0x1E, 0x36, 0x67, 0x00},// U+006B (k) - {0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00},// U+006C (l) - {0x00, 0x00, 0x33, 0x7F, 0x7F, 0x6B, 0x63, 0x00},// U+006D (m) - {0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x00},// U+006E (n) - {0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00},// U+006F (o) - {0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F},// U+0070 (p) - {0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78},// U+0071 (q) - {0x00, 0x00, 0x3B, 0x6E, 0x66, 0x06, 0x0F, 0x00},// U+0072 (r) - {0x00, 0x00, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x00},// U+0073 (s) - {0x08, 0x0C, 0x3E, 0x0C, 0x0C, 0x2C, 0x18, 0x00},// U+0074 (t) - {0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00},// U+0075 (u) - {0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00},// U+0076 (v) - {0x00, 0x00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0x00},// U+0077 (w) - {0x00, 0x00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x00},// U+0078 (x) - {0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x1F},// U+0079 (y) - {0x00, 0x00, 0x3F, 0x19, 0x0C, 0x26, 0x3F, 0x00},// U+007A (z) - {0x38, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, 0x38, 0x00},// U+007B ({) - {0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00},// U+007C (|) - {0x07, 0x0C, 0x0C, 0x38, 0x0C, 0x0C, 0x07, 0x00},// U+007D (}) - {0x6E, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// U+007E (~) - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // U+007F - }; - return (unsigned long long int *) f[c]; -} - -void printc_location (point_t point, char c) { - unsigned char const * bitmap = (unsigned char const *) font (c); - for (int i = 0; i < FONT_SIZE; i++) { - for (int j = 0; j < FONT_SIZE; j++) { - bool is_on = bitmap[i] & (1 << j); - - point_t _point; - for (int k = 0; k < FONT_FACTOR; k++) { - for (int h = 0; h < FONT_FACTOR; h++) { - _point.x = point.x + j * FONT_FACTOR + k; - _point.y = point.y + i * FONT_FACTOR + h; - drawpx (_point, is_on ? font_fg : font_bg); - } - } - } - } -} - -void printc (char c) { - // Handle special characters, print otherwise - switch (c) { - case '\r':// Reset cursor to beginning of line - cursor.x = 0; - break; - case '\n':// Move cursor to next line - cursor.y += FONT_REAL_HEIGHT; - break; - case '\t':// Print minimum one space, then align forwards to tab grid - cursor.x += FONT_TAB_REAL_WIDTH - cursor.x % (FONT_TAB_REAL_WIDTH); - break; - default:// Print character and update cursor - // TODO dynamically deal with unprintable characters (i.e., check if bitmap is all '0') - printc_location (cursor, c); - cursor.x += FONT_REAL_WIDTH; - } - - // If next printed char overflowed screen width move cursor to beginning of next line - if (cursor.x + FONT_REAL_WIDTH >= get_max_width ()) { - cursor.x = 0; - cursor.y += FONT_REAL_HEIGHT; - } - // If next line would overflow screen height (ignoring line spacing) move to beginning of screen - if (cursor.y + FONT_REAL_WIDTH - FONT_SPACING >= get_max_height ()) { -#ifndef FONT_SCROLLBACK - cursor.y -= FONT_SB_LINES * FONT_REAL_HEIGHT; - unsigned int remove_size = FONT_SB_LINES * FONT_REAL_HEIGHT * get_fb_info ()->pitch; - unsigned int scroll_size = get_fb_info ()->fb_size - remove_size; - memcpy ((ptr_t) get_fb (), (ptr_t) get_fb () + remove_size, scroll_size); - memzero ((ptr_t) get_fb () + scroll_size, remove_size); -#else - // TODO clear framebuffer here...? - cursor.y = 0; -#endif - } -} - -void font_set_normal (void) { - font_fg = font_normal_fg; -} -void font_set_error (void) { - font_fg = font_error_fg; -} - -void putc_screen (void * p, char c) { - printc (c); -} diff --git a/bulb/src/common/gpu.c b/bulb/src/common/gpu.c deleted file mode 100644 index 4b376da..0000000 --- a/bulb/src/common/gpu.c +++ /dev/null @@ -1,137 +0,0 @@ -#include "common/gpu.h" - -bool init_gpu () { - { // First message: read physical dimensions - int c = 0;// Message size; increment while we write - gpu_msg_buffer[++c] = 0;// Response - will be 0x80000000 for SUCCESS or 0x80000001 for FAILURE - - gpu_msg_buffer[++c] = 0x00040003;// Tag to get physical display width / height - gpu_msg_buffer[++c] = 8; // Size of value buffer - gpu_msg_buffer[++c] = 0; // Response & value buffer size written will be written here - gpu_msg_buffer[++c] = 0; // Get physical screen width | Overwritten by actual width - gpu_msg_buffer[++c] = 0; // Get physical screen height | Overwritten by actual height - gpu_msg_buffer[++c] = 0; // End tag - - gpu_msg_buffer[0] = (4 * ++c);// Write message size at the beginning of the buffer - - // If reading physical screen dimension fails exit function - if (! mailbox_request (gpu_msg_buffer, PROPERTY_ARM_VC)) - return false; - } - { // Second message: request frame buffer - int c = 0;// Message size; increment while we write - gpu_msg_buffer[++c] = 0;// Response - will be 0x80000000 for SUCCESS or 0x80000001 for FAILURE - -#ifdef GPU_OVERRIDE_PHYSICAL_SCREEN // If this is set, update physical /virtual dimensions based on constants - gpu_msg_buffer[++c] = 0x00048003; // Tag to set virtual display width / height - gpu_msg_buffer[++c] = 8; // Size of value buffer - gpu_msg_buffer[++c] = 0; // Response & value buffer size written will be written here - gpu_msg_buffer[++c] = GPU_SCREEN_WIDTH;// Set virtual screen width | Overwritten by actual virtual width - int index_gpu_width = c; - gpu_msg_buffer[++c] = GPU_SCREEN_HEIGHT;// Set virtual screen height | Overwritten by actual virtual height - int index_gpu_height = c; - - gpu_msg_buffer[++c] = 0x00048004; // Tag to set virtual display width / height - gpu_msg_buffer[++c] = 8; // Size of value buffer - gpu_msg_buffer[++c] = 0; // Response & value buffer size written will be written here - gpu_msg_buffer[++c] = GPU_VIRTUAL_WIDTH;// Set virtual screen width | Overwritten by actual virtual width - int index_width = c; - gpu_msg_buffer[++c] = GPU_VIRTUAL_HEIGHT;// Set virtual screen height | Overwritten by actual virtual height - int index_height = c; -#else - gpu_msg_buffer[++c] = 0x00048004;// Tag to set virtual display width / height - gpu_msg_buffer[++c] = 8; // Size of value buffer - gpu_msg_buffer[++c] = 0; // Response & value buffer size written will be written here - gpu_msg_buffer[++c]; //GPU_SCREEN_WIDTH; // Reuse previous width | Overwritten by actual virtual width - int index_width = c; - gpu_msg_buffer[++c];//GPU_SCREEN_HEIGHT; // Reuse previous height | Overwritten by actual virtual height - int index_height = c; -#endif - - gpu_msg_buffer[++c] = 0x00048005; // Tag to set pixel depth - gpu_msg_buffer[++c] = 4; // Size of value buffer - gpu_msg_buffer[++c] = 0; // Response & value buffer size written will be written here - gpu_msg_buffer[++c] = GPU_COLOUR_DEPTH;// Set colour depth | Overwritten by actual colour depth - - gpu_msg_buffer[++c] = 0x00040001;// Tag to allocate framebuffer - gpu_msg_buffer[++c] = 8; // Size of value buffer - gpu_msg_buffer[++c] = 0; // Response & value buffer size will be written here - gpu_msg_buffer[++c] = 16; // Buffer alignment | Overwritten by pointer to framebuffer - int index_framebuffer = c; - gpu_msg_buffer[++c] = 0;// Unused - will be overwritten | Overwritten by size of framebuffer - int index_fb_size = c; - - gpu_msg_buffer[++c] = 0;// End tag - gpu_msg_buffer[++c] = 0;// Padding - gpu_msg_buffer[++c] = 0;// Padding - gpu_msg_buffer[++c] = 0;// Padding - - gpu_msg_buffer[0] = (4 * ++c);// Write message size at the beginning of the buffer - - // If message failed exit - if (! mailbox_request (gpu_msg_buffer, PROPERTY_ARM_VC)) - return false; - - // Since message succeeded, update frame buffer and its size - fb_info.fb = (color_t *) (long) (gpu_msg_buffer[index_framebuffer] & VC_SDRAM_OFFSET); - fb_info.fb_size = gpu_msg_buffer[index_fb_size]; - - // printf ("PHY_WIDTH: %d, PHY_HEIGHT: %d, VIRT_WIDTH: %d, VIRT_HEIGHT: %d\n\r", gpu_msg_buffer[index_gpu_width], gpu_msg_buffer[index_gpu_height], gpu_msg_buffer[index_width], gpu_msg_buffer[index_height]); - - fb_info.virtual_width = gpu_msg_buffer[index_width]; - fb_info.virtual_height = gpu_msg_buffer[index_height]; - } - { // Third message: read pitch (in bytes per line) - int c = 0;// Message size; increment while we write - gpu_msg_buffer[++c] = 0;// Response - will be 0x80000000 for SUCCESS or 0x80000001 for FAILURE - - gpu_msg_buffer[++c] = 0x00040008;// Tag to get pitch - gpu_msg_buffer[++c] = 4; // Size of value buffer - gpu_msg_buffer[++c] = 0; // Response & value buffer size written will be written here - gpu_msg_buffer[++c] = 0; // Pitch will be written here - int index_pitch = c; - - gpu_msg_buffer[++c] = 0;// End tag - gpu_msg_buffer[++c] = 0;// Padding - - gpu_msg_buffer[0] = (4 * ++c);// Write message size at the beginning of the buffer - - // If message failed exit - if (! mailbox_request (gpu_msg_buffer, PROPERTY_ARM_VC)) - return false; - - // Else write pitch appropriately - fb_info.pitch = gpu_msg_buffer[index_pitch]; - } - return true; -} - -color_t * get_fb () { - return fb_info.fb; -} - -fb_info_t const * get_fb_info () { - return &fb_info; -} - -bool blank_screen (bool blank) { - int c = 0;// Message size; increment while we write - gpu_msg_buffer[++c] = 0;// Response - will be 0x80000000 for SUCCESS or 0x80000001 for FAILURE - - gpu_msg_buffer[++c] = 0x00040002;// Tag to blank screen - gpu_msg_buffer[++c] = 4; // Size of value buffer - gpu_msg_buffer[++c] = 0; // - gpu_msg_buffer[++c] = blank; // On or off - - gpu_msg_buffer[++c] = 0;// End tag - gpu_msg_buffer[++c] = 0;// Padding - - gpu_msg_buffer[0] = (4 * ++c);// Write message size at the beginning of the buffer - - return mailbox_request (gpu_msg_buffer, PROPERTY_ARM_VC); -} - -bool toggle_blank_screen (void) { - static bool is_blank = false; - blank_screen (is_blank = ! is_blank); -} \ No newline at end of file diff --git a/bulb/src/common/printf.c b/bulb/src/common/printf.c deleted file mode 100644 index 059ee24..0000000 --- a/bulb/src/common/printf.c +++ /dev/null @@ -1,243 +0,0 @@ -/* -File: printf.c - -Copyright (C) 2004 Kustaa Nyholm - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library 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 -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include "common/printf.h" - -typedef void (*putcf) (void *, char); - -static putcf stdout_putf; -static void * stdout_putp; - - -#ifdef PRINTF_LONG_SUPPORT - -static void uli2a (unsigned long int num, unsigned int base, int uc, char * bf) { - int n = 0; - unsigned int d = 1; - while (num / d >= base) - d *= base; - while (d != 0) { - int dgt = num / d; - num %= d; - d /= base; - if (n || dgt > 0 || d == 0) { - *bf++ = dgt + (dgt < 10 ? '0' : (uc ? 'A' : 'a') - 10); - ++n; - } - } - *bf = 0; -} - -static void li2a (long num, char * bf) { - if (num < 0) { - num = -num; - *bf++ = '-'; - } - uli2a (num, 10, 0, bf); -} - -#endif - -static void ui2a (unsigned int num, unsigned int base, int uc, char * bf) { - int n = 0; - unsigned int d = 1; - while (num / d >= base) - d *= base; - while (d != 0) { - int dgt = num / d; - num %= d; - d /= base; - if (n || dgt > 0 || d == 0) { - *bf++ = dgt + (dgt < 10 ? '0' : (uc ? 'A' : 'a') - 10); - ++n; - } - } - *bf = 0; -} - -static void i2a (int num, char * bf) { - if (num < 0) { - num = -num; - *bf++ = '-'; - } - ui2a (num, 10, 0, bf); -} - -static int a2d (char ch) { - if (ch >= '0' && ch <= '9') { - return ch - '0'; - } else if (ch >= 'a' && ch <= 'f') { - return ch - 'a' + 10; - } else if (ch >= 'A' && ch <= 'F') { - return ch - 'A' + 10; - } else { - return -1; - } -} - -static char a2i (char ch, char ** src, int base, int * nump) { - char * p = *src; - int num = 0; - int digit; - while ((digit = a2d (ch)) >= 0) { - if (digit > base) - break; - num = num * base + digit; - ch = *p++; - } - *src = p; - *nump = num; - return ch; -} - -static void putchw (void * putp, putcf putf, int n, char z, char * bf) { - char fc = z ? '0' : ' '; - char ch; - char * p = bf; - while (*p++ && n > 0) - n--; - while (n-- > 0) - putf (putp, fc); - while ((ch = *bf++)) - putf (putp, ch); -} - -void tfp_format (void * putp, putcf putf, char * fmt, va_list va) { - char bf[12]; - - char ch; - - - while ((ch = *(fmt++))) { - if (ch != '%') { - putf (putp, ch); - } else { - char lz = 0; -#ifdef PRINTF_LONG_SUPPORT - char lng = 0; -#endif - int w = 0; - ch = *(fmt++); - if (ch == '0') { - ch = *(fmt++); - lz = 1; - } - if (ch >= '0' && ch <= '9') { - ch = a2i (ch, &fmt, 10, &w); - } -#ifdef PRINTF_LONG_SUPPORT - if (ch == 'l') { - ch = *(fmt++); - lng = 1; - } -#endif - switch (ch) { - case 0: - goto abort; - case 'u': { -#ifdef PRINTF_LONG_SUPPORT - if (lng) - uli2a (va_arg (va, unsigned long int), 10, 0, bf); - else -#endif - ui2a (va_arg (va, - unsigned int), 10, 0, bf); - putchw (putp, putf, w, lz, bf); - break; - } - case 'd': { -#ifdef PRINTF_LONG_SUPPORT - if (lng) - li2a (va_arg (va, unsigned long int), bf); - else -#endif - i2a (va_arg (va, - int), bf); - putchw (putp, putf, w, lz, bf); - break; - } - case 'x': - case 'X': -#ifdef PRINTF_LONG_SUPPORT - if (lng) - uli2a (va_arg (va, unsigned long int), 16, (ch == 'X'), bf); - else -#endif - ui2a (va_arg (va, - unsigned int), 16, (ch == 'X'), bf); - putchw (putp, putf, w, lz, bf); - break; - case 'c' : - putf (putp, (char) (va_arg (va, - int))); - break; - case 's' : - putchw (putp, putf, w, 0, va_arg (va, - char*)); - break; - case 'p': - case 'P': - putf (putp, '0'); - putf (putp, 'x'); -#ifdef PRINTF_LONG_SUPPORT - if (lng) - uli2a (va_arg (va, unsigned long int), 16, (ch == 'P'), bf); - else -#endif - ui2a (va_arg (va, - unsigned int), 16, (ch == 'P'), bf); - putchw (putp, putf, w, lz, bf); - break; - case '%': - putf (putp, ch); - default: - break; - } - } - } -abort:; -} - - -void init_printf (void * putp, void (*putf) (void *, char)) { - stdout_putf = putf; - stdout_putp = putp; -} - -void tfp_printf (char * fmt, ...) { - va_list va; - va_start (va, fmt); - tfp_format (stdout_putp, stdout_putf, fmt, va); - va_end (va); -} - -static void putcp (void * p, char c) { - *(*((char **) p))++ = c; -} - - -void tfp_sprintf (char * s, char * fmt, ...) { - va_list va; - va_start (va, fmt); - tfp_format (&s, putcp, fmt, va); - putcp (&s, 0); - va_end (va); -} diff --git a/bulb/src/common/screen.c b/bulb/src/common/screen.c deleted file mode 100644 index b09764d..0000000 --- a/bulb/src/common/screen.c +++ /dev/null @@ -1,14 +0,0 @@ -#include "common/screen.h" - -void drawpx (point_t p, color_t color) { - unsigned long int location = p.y * (get_fb_info ()->pitch) / sizeof (color_t) + p.x; - get_fb ()[location] = color; -}; - -short get_max_width () { - return get_fb_info ()->virtual_width - 1; -} - -short get_max_height () { - return get_fb_info ()->virtual_height - 1; -} diff --git a/bulb/src/common/status_led.c b/bulb/src/common/status_led.c deleted file mode 100644 index b8b1b03..0000000 --- a/bulb/src/common/status_led.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "common/status_led.h" - -bool get_led (int pin) { - // Try to read ACT LED state - int c = 0;// Message size; increment while we write - led_msg_buffer[++c] = 0;// Response - will be 0x80000000 for SUCCESS or 0x80000001 for FAILURE - - led_msg_buffer[++c] = 0x00030041;// Tag to get ACT LED state - led_msg_buffer[++c] = 8; // Size of value buffer - led_msg_buffer[++c] = 0; // Response & value buffer size written will be written here - led_msg_buffer[++c] = pin; // - led_msg_buffer[++c] = 0; // - int index_led = c; - - led_msg_buffer[++c] = 0;// End tag - - led_msg_buffer[0] = (4 * ++c);// Write message size at the beginning of the buffer - - if (! mailbox_request (led_msg_buffer, PROPERTY_ARM_VC)) { - printf ("ERROR\r\n"); - }; - return ! led_msg_buffer[index_led]; -} - -/** - * Change LED state - * Pins: - * - Power LED: 130 (0 to turn on and 1 to turn off) - * - ACT LED: 42 (1 to turn on and 0 to turn off) -**/ -void set_led (bool status, int pin) { - // Try to read ACT LED state - int c = 0;// Message size; increment while we write - led_msg_buffer[++c] = 0;// Response - will be 0x80000000 for SUCCESS or 0x80000001 for FAILURE - - led_msg_buffer[++c] = 0x00038041;// Tag to get ACT LED state - led_msg_buffer[++c] = 8; // Size of value buffer - led_msg_buffer[++c] = 0; // Response & value buffer size written will be written here - led_msg_buffer[++c] = pin; - led_msg_buffer[++c] = status; - - led_msg_buffer[++c] = 0;// End tag - - led_msg_buffer[0] = (4 * ++c);// Write message size at the beginning of the buffer - - if (! mailbox_request (led_msg_buffer, PROPERTY_ARM_VC)) { - printf ("ERROR\r\n"); - }; -} - -bool toggle_led (int pin) { - bool status = get_led (pin); - set_led (status, pin); - return status; -} diff --git a/bulb/src/common/utils.S b/bulb/src/common/utils.S deleted file mode 100644 index 44be485..0000000 --- a/bulb/src/common/utils.S +++ /dev/null @@ -1,21 +0,0 @@ -.globl get_el -get_el: - mrs x0, CurrentEL - lsr x0, x0, #2 - ret - -.globl put32 -put32: - str w1,[x0] - ret - -.globl get32 -get32: - ldr w0,[x0] - ret - -.globl delay -delay: - subs x0, x0, #1 - bne delay - ret diff --git a/bulb/src/config.txt b/bulb/src/config.txt deleted file mode 100644 index 1cb4eed..0000000 --- a/bulb/src/config.txt +++ /dev/null @@ -1,2 +0,0 @@ -enable_uart=1 -dtparam=watchdog=on diff --git a/bulb/src/kernel/boot.S b/bulb/src/kernel/boot.S deleted file mode 100644 index 14bc88a..0000000 --- a/bulb/src/kernel/boot.S +++ /dev/null @@ -1,52 +0,0 @@ -#include "kernel/arm/sysregs.h" - -#include "kernel/mm.h" - -.section ".text.boot" - -.globl _start -_start: - mrs x0, mpidr_el1 - and x0, x0,#0xFF // Check processor id - cbz x0, init_bss // Hang for all non-primary CPU - - wfe - - b master - -init_bss: - adr x0, __bss_start - adr x1, __bss_end - sub x1, x1, x0 - bl memzero - - b move_to_el1 - -move_to_el1: - ldr x0, =SCTLR_VALUE_MMU_DISABLED - msr sctlr_el1, x0 - - ldr x0, =HCR_VALUE - msr hcr_el2, x0 - - ldr x0, =SPSR_VALUE - msr spsr_el2, x0 - - adr x0, master - msr elr_el2, x0 - - eret - -master: - mrs x0, mpidr_el1 - and x0, x0, #0xFF - mov x1, #SECTION_SIZE - mul x1, x1, x0 - add x1, x1, #LOW_MEMORY - mov sp, x1 - - bl kernel_main - -proc_hang: - b proc_hang - diff --git a/bulb/src/kernel/entry.S b/bulb/src/kernel/entry.S deleted file mode 100644 index dcbbce8..0000000 --- a/bulb/src/kernel/entry.S +++ /dev/null @@ -1,181 +0,0 @@ -#include "kernel/arm/sysregs.h" -#include "kernel/entry.h" -#include "kernel/mmu.h" - - .macro handle_invalid_entry el, type - kernel_entry \el - mov x0, #\type - mrs x1, esr_el1 - mrs x2, elr_el1 - bl show_invalid_entry_message - b err_hang - .endm - - .macro ventry label - .align 7 - b \label - .endm - - .macro kernel_entry, el - sub sp, sp, #S_FRAME_SIZE - 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] - - .if \el == 0 - mrs x21, sp_el0 - .else - add x21, sp, #S_FRAME_SIZE - .endif /* \el == 0 */ - - mrs x22, elr_el1 - mrs x23, spsr_el1 - - stp x30, x21, [sp, #16 * 15] - stp x22, x23, [sp, #16 * 16] - .endm - - .macro kernel_exit, el - ldp x22, x23, [sp, #16 * 16] - ldp x30, x21, [sp, #16 * 15] - - .if \el == 0 - msr sp_el0, x21 - .endif /* \el == 0 */ - - msr elr_el1, x22 - msr spsr_el1, x23 - - - 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] - add sp, sp, #S_FRAME_SIZE - eret - .endm - - -/* - * Exception vectors. - */ -.align 11 -.globl vectors -vectors: - ventry sync_invalid_el1t // Synchronous EL1t - ventry irq_invalid_el1t // IRQ EL1t - ventry fiq_invalid_el1t // FIQ EL1t - ventry error_invalid_el1t // Error EL1t - - ventry el0_sync // Synchronous EL1h - ventry el1_irq // IRQ EL1h - ventry fiq_invalid_el1h // FIQ EL1h - ventry error_invalid_el1h // Error EL1h - - ventry el0_sync // Synchronous 64-bit EL0 - ventry el0_irq // IRQ 64-bit EL0 - ventry fiq_invalid_el0_64 // FIQ 64-bit EL0 - ventry error_invalid_el0_64 // Error 64-bit EL0 - - ventry sync_invalid_el0_32 // Synchronous 32-bit EL0 - ventry irq_invalid_el0_32 // IRQ 32-bit EL0 - ventry fiq_invalid_el0_32 // FIQ 32-bit EL0 - ventry error_invalid_el0_32 // Error 32-bit EL0 - -sync_invalid_el1t: - handle_invalid_entry 1, SYNC_INVALID_EL1t - -irq_invalid_el1t: - handle_invalid_entry 1, IRQ_INVALID_EL1t - -fiq_invalid_el1t: - handle_invalid_entry 1, FIQ_INVALID_EL1t - -error_invalid_el1t: - handle_invalid_entry 1, ERROR_INVALID_EL1t - -sync_invalid_el1h: - handle_invalid_entry 1, SYNC_INVALID_EL1h - -fiq_invalid_el1h: - handle_invalid_entry 1, FIQ_INVALID_EL1h - -error_invalid_el1h: - handle_invalid_entry 1, ERROR_INVALID_EL1h - -fiq_invalid_el0_64: - handle_invalid_entry 0, FIQ_INVALID_EL0_64 - -error_invalid_el0_64: - handle_invalid_entry 0, ERROR_INVALID_EL0_64 - -sync_invalid_el0_32: - handle_invalid_entry 0, SYNC_INVALID_EL0_32 - -irq_invalid_el0_32: - handle_invalid_entry 0, IRQ_INVALID_EL0_32 - -fiq_invalid_el0_32: - handle_invalid_entry 0, FIQ_INVALID_EL0_32 - -error_invalid_el0_32: - handle_invalid_entry 0, ERROR_INVALID_EL0_32 - -el1_irq: - kernel_entry 1 - bl handle_irq - kernel_exit 1 - -el0_irq: - kernel_entry 0 - bl handle_irq - kernel_exit 0 - -el0_sync: - kernel_entry 0 - - mrs x25, esr_el1 - lsr x24, x25, #ESR_ELx_EC_SHIFT - cmp x24, #ESR_ELx_EC_DABT_SAME - b.eq el1_da - - handle_invalid_entry 0, SYNC_ERROR - -sc_nr .req x25 // number of system calls -scno .req x26 // syscall number -stbl .req x27 // syscall table pointer - -el1_da: - bl enable_irq - mrs x0, far_el1 - mrs x1, esr_el1 - bl data_abort_el1 - bl disable_irq - eret - -.globl err_hang -err_hang: b err_hang - diff --git a/bulb/src/kernel/irq.S b/bulb/src/kernel/irq.S deleted file mode 100644 index ad54157..0000000 --- a/bulb/src/kernel/irq.S +++ /dev/null @@ -1,15 +0,0 @@ -.globl irq_vector_init -irq_vector_init: - adr x0, vectors // load VBAR_EL1 with virtual - msr vbar_el1, x0 // vector table address - ret - -.globl enable_irq -enable_irq: - msr daifclr, #2 - ret - -.globl disable_irq -disable_irq: - msr daifset, #2 - ret diff --git a/bulb/src/kernel/irq.c b/bulb/src/kernel/irq.c deleted file mode 100644 index 7ca1047..0000000 --- a/bulb/src/kernel/irq.c +++ /dev/null @@ -1,51 +0,0 @@ -#include "kernel/irq.h" - -const char * entry_error_messages[] = { - "SYNC_INVALID_EL1t", "IRQ_INVALID_EL1t", "FIQ_INVALID_EL1t", "ERROR_INVALID_EL1T", "SYNC_INVALID_EL1h", "IRQ_INVALID_EL1h", "FIQ_INVALID_EL1h", "ERROR_INVALID_EL1h", "SYNC_INVALID_EL0_64", "IRQ_INVALID_EL0_64", "FIQ_INVALID_EL0_64", "ERROR_INVALID_EL0_64", "SYNC_INVALID_EL0_32", "IRQ_INVALID_EL0_32", "FIQ_INVALID_EL0_32", "ERROR_INVALID_EL0_32", "SYNC_ERROR", "SYSCALL_ERROR"}; - -void enable_interrupt (unsigned int irq) { - printf ("Interrupt pointer %p\r\n", irq); - unsigned int n = irq / 32; - unsigned int offset = irq % 32; - unsigned int enableRegister = GICD_ENABLE_IRQ_BASE + (4 * n); - printf ("EnableRegister: %x\r\n", enableRegister); - put32 (enableRegister, 1 << offset); -} - -void assign_target (unsigned int irq, unsigned int cpu) { - unsigned int n = irq / 4; - unsigned int targetRegister = GIC_IRQ_TARGET_BASE + (4 * n); - // Currently we only enter the target CPU 0 - put32 (targetRegister, get32 (targetRegister) | (1 << 8)); -} - -void show_invalid_entry_message (int type, ptr_t esr, ptr_t address) { - printf ("Type %s, ESR: %p, address, %p\r\n", entry_error_messages[type], (void *) esr, (void *) address); -} - -void enable_interrupt_controller () { - assign_target (SYSTEM_TIMER_IRQ_1, 0); - put32 (ENABLE_IRQS_1, SYSTEM_TIMER_IRQ_1 -#ifdef _ROSE_K_MINI_UART_H - | ENABLE_AUX_INT -#endif - ); - enable_interrupt (SYSTEM_TIMER_IRQ_1); -} - -void handle_irq (void) { - unsigned int irq_ack_reg = get32 (GICC_IAR); - unsigned int irq1 = irq_ack_reg & 0x2FF; - if (irq1 & SYSTEM_TIMER_IRQ_1) { - put32 (GICC_EOIR, irq_ack_reg); - handle_timer_irq (); - } - -#ifdef _ROSE_K_MINI_UART_H - unsigned int irq2 = get32 (AUX_IRQ_REG); - if (irq2 & MINI_UART_IRQ) { - put32 (GICC_EOIR, irq_ack_reg); - handle_mini_uart_irq (); - } -#endif -} diff --git a/bulb/src/kernel/kernel.c b/bulb/src/kernel/kernel.c deleted file mode 100644 index 629c1a4..0000000 --- a/bulb/src/kernel/kernel.c +++ /dev/null @@ -1,64 +0,0 @@ -#include "kernel/mini_uart.h" -// -#include "common/font.h" -#include "common/gpu.h" -#include "common/logging.h" -#include "common/printf.h" -#include "common/status_led.h" -#include "common/utils.h" -#include "kernel/entry.h" -#include "kernel/irq.h" -#include "kernel/mm.h" -#include "kernel/mmu.h" - -void hang (int led, int cycles) { - while (1) { - toggle_led (led); - delay (cycles); - } -} - -void dual_print (void * p, char c) { - printc (c); - uart_send (c); -} - -void kernel_init (void) { - set_led (0, POWER_LED); - set_led (0, STATUS_LED); - - uart_init (); - init_printf (0, putc); - - if (init_gpu ()) { - if (get_fb ()) { - font_set_normal (); - init_printf (0, putc_screen); - printf ("Frame buffer: %p\r\n", get_fb ()); - printf ("Width resolution: %d\r\n", get_fb_info ()->virtual_width); - printf ("Height resolution: %d\r\n", get_fb_info ()->virtual_height); - - LOG ("Initialisation done"); - ERROR ("I'm important!"); - } else - hang (POWER_LED, 1000000); - } else - hang (POWER_LED, 2000000); - init_printf (0, dual_print); - - timer_init (); - irq_vector_init (); - enable_interrupt_controller (); - enable_irq (); -} - -void kernel_main (int processor_id) { - kernel_init (); - - init_mmu (); - - printf ("Hello, from processor %d in EL %d\r\n", processor_id, get_el ()); - uart_send ("EVERYTHING WORKS!!!\r\n"); - - hang (POWER_LED, 5000000); -} diff --git a/bulb/src/kernel/mailbox.c b/bulb/src/kernel/mailbox.c deleted file mode 100644 index a744c50..0000000 --- a/bulb/src/kernel/mailbox.c +++ /dev/null @@ -1,52 +0,0 @@ -#include "kernel/mailbox.h" - -bool mailbox_request (volatile unsigned int * data_ptr, channel_t channel) { - volatile unsigned int * buffer = data_ptr; - - if (DUMP_BUFFER) { - LOG ("Dumping message buffer before sending:"); - int_dump ((unsigned int *) buffer); - hex_dump ((byte_t *) buffer); - } - - // 28-bit address (MSB) and 4-bit value (LSB) - unsigned int outgoing = ((unsigned int) ((long) data_ptr) & ~0xF) | (channel & 0xF); - - // Wait until we can write - while (get32 (MBOX0 + MBOX_STATUS) & MBOX_WRITE_FULL) - ; - - // Write the address of our buffer to the mailbox with the channel appended - put32 (MBOX0 + MBOX_WRITE, outgoing); - - unsigned int incoming; - while (1) { - // Is there a reply? - while (get32 (MBOX0 + MBOX_STATUS) & MBOX_READ_EMPTY) - ; - - incoming = get32 (MBOX0 + MBOX_READ); - - // Is it a reply to our message? - if (outgoing == incoming) { - if (buffer[1] != MBOX_SUCCESS) { - if (DUMP_BUFFER) { - LOG ("Dumping failed message buffer:"); - int_dump ((unsigned int *) buffer); - hex_dump ((byte_t *) buffer); - } - - return false; - } - break; - } - } - - if (DUMP_BUFFER) { - LOG ("Dumping successful message buffer:"); - int_dump ((unsigned int *) buffer); - hex_dump ((byte_t *) buffer); - } - - return true; -} diff --git a/bulb/src/kernel/mini_uart.c b/bulb/src/kernel/mini_uart.c deleted file mode 100644 index 64b005e..0000000 --- a/bulb/src/kernel/mini_uart.c +++ /dev/null @@ -1,87 +0,0 @@ -#include "kernel/mini_uart.h" - -void mini_uart_send (char c) { - while (1) { - if (get32 (AUX_MU_LSR_REG) & 0x20) { - break; - } - } - put32 (AUX_MU_IO_REG, c); -} - -char mini_uart_recv (void) { - while (1) { - if (get32 (AUX_MU_LSR_REG) & 0x01) { - break; - } - } - return (get32 (AUX_MU_IO_REG) & 0xFF); -} - -void mini_uart_send_string (char * str) { - for (int i = 0; str[i] != '\0'; i++) { - mini_uart_send ((char) str[i]); - } -} - -void mini_uart_init (void) { - static volatile bool init_progress = false; - static volatile bool init_done = false; - - if (init_progress) { - while (!init_done) - ; - return; - } - init_progress = true; - - unsigned int selector; - int target = BAUD_RATE_REG (115200); - - selector = get32 (GPFSEL1); - selector &= ~(7 << 12); - selector |= 2 << 12; - selector &= ~(7 << 15); - selector |= 2 << 15; - put32 (GPFSEL1, selector); - - put32 (GPPUD, 0); - delay (150); - put32 (GPPUDCLK0, (1 << 14) | (1 << 15)); - delay (150); - put32 (GPPUDCLK0, 0); - - put32 (AUX_ENABLES, 1); - put32 (AUX_MU_CNTL_REG, 0); - put32 (AUX_MU_IER_REG, ENABLE_MU_REC_INT); - put32 (AUX_MU_LCR_REG, 3); - put32 (AUX_MU_MCR_REG, 0); - put32 (AUX_MU_BAUD_REG, target); - - put32 (AUX_MU_CNTL_REG, 3); - - mini_uart_send_string ("\033[2J\033[H"); - mini_uart_send_string ("Initialised mini UART\r\n"); - - init_done = true; -} - -void handle_mini_uart_irq (void) { - char c_event = mini_uart_recv (); - switch (c_event) { - case 17:// device control 1 - mini_uart_send_string ("Power off"); - poweroff (40, true);// power off instantly, never return control here - case 18: // device control 2 - mini_uart_send_string ("Reboot"); - reboot (40, true);// reboot instantly, never return control here - case 19: - toggle_blank_screen (); - default: - mini_uart_send (c_event); - } -} - -void mini_putc (void * p, char c) { - mini_uart_send (c); -} \ No newline at end of file diff --git a/bulb/src/kernel/mm.S b/bulb/src/kernel/mm.S deleted file mode 100644 index 92e5692..0000000 --- a/bulb/src/kernel/mm.S +++ /dev/null @@ -1,14 +0,0 @@ -.globl memcpy -memcpy: - ldr x3, [x1], #8 - str x3, [x0], #8 - subs x2, x2, #8 - b.gt memcpy - ret - -.globl memzero -memzero: - str xzr, [x0], #8 - subs x1, x1, #8 - b.gt memzero - ret diff --git a/bulb/src/kernel/mm.c b/bulb/src/kernel/mm.c deleted file mode 100644 index f4da23c..0000000 --- a/bulb/src/kernel/mm.c +++ /dev/null @@ -1,19 +0,0 @@ -#include "kernel/mm.h" - -static unsigned short mem_map[PAGING_PAGES] = { - 0, -}; - -ptr_t get_free_page () { - for (int i = 0; i < PAGING_PAGES; i++) { - if (mem_map[i] == 0) { - mem_map[i] = 1; - return LOW_MEMORY + i * PAGE_SIZE; - } - } - return 0; -} - -void free_page (ptr_t p) { - mem_map[(p - LOW_MEMORY) / PAGE_SIZE] = 0; -} diff --git a/bulb/src/kernel/mmu.c b/bulb/src/kernel/mmu.c deleted file mode 100644 index 1e11103..0000000 --- a/bulb/src/kernel/mmu.c +++ /dev/null @@ -1,175 +0,0 @@ -#include "kernel/mmu.h" - -static volatile unsigned int buffer[] = {32, 0, 0x00038041, 8, 0, 42, 1, 0}; - -void init_pages () { - unsigned long data_page = (unsigned long) &_data / PAGESIZE; - unsigned long r, b, *paging = (unsigned long *) &_end; - - unsigned long * PUD0 = paging + 0 * 512; - unsigned long * PMD0 = paging + 2 * 512; - unsigned long * PTE0 = paging + 1 * 512; - - /* create MMU translation tables at _end */ - // TTBR0, identity L1 - b = PBASE >> 21; - for (int i = 0; i < RAM_IN_GB; i++) { - PUD0[i] = (unsigned long) ((unsigned char *) &_end + (2 + i) * PAGESIZE) |// physical address - PT_PAGE | // it has the "Present" flag, which must be set, and we have area in it mapped by pages - PT_AF | // accessed flag. Without this we're going to have a Data Abort exception - PT_USER | // non-privileged - PT_ISH | // inner shareable - PT_MEM; // normal memory - - unsigned int offset = i * 512; - // identity L2 2M blocks - for (r = 0; r < 512; r++) - PMD0[i * 512 + r] = (unsigned long) ((offset + r) << 21) | // physical address - PT_BLOCK | // map 2M block - PT_AF | // accessed flag - PT_USER | // non-privileged - (offset + r >= b ? PT_OSH | PT_DEV : PT_ISH | PT_MEM);// different attributes for device memory - } - - // identity L2, first 2M block - PMD0[0] = (unsigned long) ((unsigned char *) &_end + PAGESIZE) |// physical address - PT_PAGE | // we have area in it mapped by pages - PT_AF | // accessed flag - PT_USER | // non-privileged - PT_ISH | // inner shareable - PT_MEM; // normal memory - - // identity L3 - for (r = 0; r < 512; r++) - PTE0[r] = (unsigned long) (r * PAGESIZE) | // physical address - PT_PAGE | // map 4k - PT_AF | // accessed flag - PT_USER | // non-privileged - PT_ISH | // inner shareable - ((r < 0x80 || r >= data_page) ? PT_RW : PT_RO);// different for code and data -} - -void init_mmu () { - unsigned long data_page = (unsigned long) &_data / PAGESIZE; - unsigned long r, b, *paging = (unsigned long *) &_end; - - init_pages (); - - /* okay, now we have to set system registers to enable MMU */ - // check for 4k granule and at least 36 bits physical address bus */ - asm volatile("mrs %0, id_aa64mmfr0_el1" - : "=r"(r)); - b = r & 0xF; - if (r & (0xF << 28) /*4k*/ || b < 1 /*36 bits*/) { - ERROR ("ERROR: 4k granule or 36 bit address space not supported\n"); - return; - } - LOG ("4k granule and 36bit address bus ensured"); - - // first, set Memory Attributes array, indexed by PT_MEM, PT_DEV, PT_NC in our example - r = (0xFF << 0) |// AttrIdx=0: normal, IWBWA, OWBWA, NTR - (0x04 << 8) |// AttrIdx=1: device, nGnRE (must be OSH too) - (0x44 << 16);// AttrIdx=2: non cacheable - asm volatile("msr mair_el1, %0" - : - : "r"(r)); - LOG ("MAIR attributes written"); - - // next, specify mapping characteristics in translate control register - r = (0b00LL << 37) |// TBI=0, no tagging - (b << 32) | // IPS=autodetected - (0b10LL << 30) |// TG1=4k - (0b11LL << 28) |// SH1=3 inner - (0b01LL << 26) |// ORGN1=1 write back - (0b01LL << 24) |// IRGN1=1 write back - (0b0LL << 23) | // EPD1 enable higher half - (25LL << 16) | // T1SZ=25, 3 levels (512G) - (0b00LL << 14) |// TG0=4k - (0b11LL << 12) |// SH0=3 inner - (0b01LL << 10) |// ORGN0=1 write back - (0b01LL << 8) | // IRGN0=1 write back - (0b0LL << 7) | // EPD0 enable lower half - (25LL << 0); // T0SZ=25, 3 levels (512G) - asm volatile("msr tcr_el1, %0; isb" - : - : "r"(r)); - LOG ("Translation control register written"); - - // tell the MMU where our translation tables are. TTBR_CNP bit not documented, but required - // lower half, user space - asm volatile("msr ttbr0_el1, %0" - : - : "r"((unsigned long) &_end + TTBR_CNP)); - LOG ("TTBR0 written"); - - // upper half, kernel space - asm volatile("msr ttbr1_el1, %0" - : - : "r"((unsigned long) &_end + TTBR_CNP)); - LOG ("TTBR1 written"); - - // finally, toggle some bits in system control register to enable page translation - asm volatile("dsb ish; isb; mrs %0, sctlr_el1" - : "=r"(r)); - r |= 0xC00800; // set mandatory reserved bits - r &= ~((1 << 25) |// clear EE, little endian translation tables - (1 << 24) |// clear E0E - (1 << 19) |// clear WXN - (1 << 12) |// clear I, no instruction cache - (1 << 4) | // clear SA0 - (1 << 3) | // clear SA - (1 << 2) | // clear C, no cache at all - (1 << 1)); // clear A, no aligment check - r |= (1 << 0); // set M, enable MMU - - LOG ("Read out system control register"); - - asm volatile("msr sctlr_el1, %0; isb" - : - : "r"(r)); - - LOG ("Set SCTLR flags and enable MMU"); - - *((unsigned int volatile *) (0xFE00B8A0)) = (unsigned long) buffer | 8; - LOG ("LED SWITCHING DONE"); - - printf ("Msg : %p\r\n", (unsigned long) buffer | 8); - printf ("%u ", buffer[0]); - printf ("%u ", buffer[1]); - printf ("%p ", buffer[2]); - printf ("%u ", buffer[3]); - printf ("%u ", buffer[4]); - printf ("%u ", buffer[5]); - printf ("%u ", buffer[6]); - printf ("%u \r\n", buffer[7]); - - set_led (POWER_LED, 1); -} - -void data_abort_el1 (ptr_t far, ptr_t esr) { - byte_t type = (esr >> 2) & 0b11; - byte_t level = esr & 0b11; - esr &= 0b111111; - - printf ("EL 1 - "); - printf ("FAR_EL1: %p - ", far); - printf ("ESR_EL1: %b\n\r", esr); - - switch (type) { - case 0b00:// Address size fault - printf ("Address size fault during level %ld of table walk on lookup of address %p.\r\n", level, far); - // exit_process (); - break; - case 0b01:// Translation fault - printf ("Translation fault during level %ld of table walk on lookup of address %p.\r\n", level, far); - break; - case 0b10:// Access flag fault - printf ("Access flag fault during level %ld of table walk on lookup of address %p.\r\n", level, far); - // exit_process (); - break; - case 0b11:// Permission fault - printf ("Segmentation fault during level %ld of table walk on lookup of address %p.\r\n", level, far); - // exit_process (); - break; - } -} \ No newline at end of file diff --git a/bulb/src/kernel/power.c b/bulb/src/kernel/power.c deleted file mode 100644 index bcfbc55..0000000 --- a/bulb/src/kernel/power.c +++ /dev/null @@ -1,19 +0,0 @@ -#include "kernel/power.h" - -void poweroff (unsigned int timeout, bool block) { -} - -void reboot (unsigned int timeout, bool block) { - unsigned int pm_rstc, pm_wdog; - - /* Setup watchdog for reset */ - pm_rstc = get32 (PM_RSTC); - // watchdog timer = timer clock / 16; need password (31:16) + value (11:0) - pm_wdog = PM_PASSWORD | (timeout & PM_WDOG_TIME_SET); - pm_rstc = PM_PASSWORD | (pm_rstc & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET; - put32 (PM_WDOG, pm_wdog); - put32 (PM_RSTC, pm_rstc); - - while (block) - ; -} diff --git a/bulb/src/kernel/timer.c b/bulb/src/kernel/timer.c deleted file mode 100644 index 0b3a5f6..0000000 --- a/bulb/src/kernel/timer.c +++ /dev/null @@ -1,23 +0,0 @@ -#include "kernel/peripherals/timer.h" -#include "common/printf.h" -#include "common/status_led.h" -#include "common/utils.h" -//#include "kernel/sched.h" - -const unsigned int interval = 200000; -unsigned int curVal = 0; - -void timer_init (void) { - curVal = get32 (TIMER_CLO); - curVal += interval; - put32 (TIMER_C1, curVal); -} - -void handle_timer_irq (void) { - toggle_led (STATUS_LED); - - curVal += interval; - put32 (TIMER_C1, curVal); - put32 (TIMER_CS, TIMER_CS_M1); - // timer_tick (); -} diff --git a/bulb/src/linker.ld b/bulb/src/linker.ld deleted file mode 100644 index 332bfc8..0000000 --- a/bulb/src/linker.ld +++ /dev/null @@ -1,19 +0,0 @@ -SECTIONS -{ - . = 0x80000; - .text.boot : { *(.text.boot) } - .text : { *(.text) } - .rodata : { *(.rodata) } - PROVIDE(_data = .); - .data : { *(.data) } - .bss (NOLOAD) : { - . = ALIGN(16); - __bss_start = .; - *(.bss .bss.*) - *(COMMON) - __bss_end = .; - } - . = ALIGN(4096); - _end = .; -} -__bss_size = (__bss_end - __bss_start) >> 3; \ No newline at end of file diff --git a/thorn/include/common/utils.h b/thorn/include/common/utils.h index 29b53a1..ae4222e 100644 --- a/thorn/include/common/utils.h +++ b/thorn/include/common/utils.h @@ -9,4 +9,8 @@ extern unsigned int get32 (unsigned long); extern int get_el (void); +extern void set_pgd(unsigned long pgd); + +extern unsigned long get_pgd(); + #endif /*_ROSE_C_BOOT_H */ diff --git a/thorn/include/kernel/sched.h b/thorn/include/kernel/sched.h index b2b1734..ab1c24d 100644 --- a/thorn/include/kernel/sched.h +++ b/thorn/include/kernel/sched.h @@ -39,14 +39,29 @@ struct cpu_context { unsigned long pc; }; +#define MAX_PROCESS_PAGES 16 + +struct user_page { + unsigned long phys_addr; + unsigned long virt_addr; +}; + +struct mm_struct { + unsigned long pgd; + int user_pages_count; + struct user_page user_pages[MAX_PROCESS_PAGES]; + int kernel_pages_count; + unsigned long kernel_pages[MAX_PROCESS_PAGES]; +}; + struct task_struct { struct cpu_context cpu_context; long state; long counter; long priority; long preempt_count; - ptr_t stack; - ptr_t flags; + unsigned long flags; + struct mm_struct mm; }; extern void sched_init (void); @@ -65,6 +80,8 @@ extern void cpu_switch_to (struct task_struct * prev, struct task_struct * next) extern void exit_process (void); +extern void kill_process (void); + extern void task_init (void); #define INIT_TASK \ diff --git a/thorn/src/common/utils.S b/thorn/src/common/utils.S index 44be485..1c3c8b6 100644 --- a/thorn/src/common/utils.S +++ b/thorn/src/common/utils.S @@ -19,3 +19,20 @@ delay: subs x0, x0, #1 bne delay ret + +.globl set_pgd +set_pgd: + msr ttbr0_el1, x0 + tlbi vmalle1is + DSB ISH // ensure completion of TLB invalidation + isb + ret + +.globl get_pgd +get_pgd: + mov x1, 0 + ldr x0, [x1] + mov x0, 0x1000 + msr ttbr0_el1, x0 + ldr x0, [x1] + ret diff --git a/thorn/src/kernel/entry.S b/thorn/src/kernel/entry.S index 950d6ea..9c546c8 100644 --- a/thorn/src/kernel/entry.S +++ b/thorn/src/kernel/entry.S @@ -159,8 +159,6 @@ el0_sync: kernel_entry 0 mrs x25, esr_el1 // read the syndrome register lsr x24, x25, #ESR_ELx_EC_SHIFT // exception class - cmp x24, #ESR_ELx_EC_SVC64 // SVC in 64-bit state - b.eq el0_svc cmp x24, #ESR_ELx_EC_DABT_LOW b.eq el0_da handle_invalid_entry 0, SYNC_ERROR @@ -192,8 +190,9 @@ el0_da: mrs x0, far_el1 mrs x1, esr_el1 bl data_abort_el0 - bl disable_irq - eret + bl disable_irq + bl kill_process + eret .globl ret_from_fork ret_from_fork: diff --git a/thorn/src/kernel/fork.c b/thorn/src/kernel/fork.c index 799f931..dab1a81 100644 --- a/thorn/src/kernel/fork.c +++ b/thorn/src/kernel/fork.c @@ -14,6 +14,11 @@ int copy_process (ptr_t clone_flags, ptr_t fn, ptr_t arg, ptr_t stack) { return -1; } + p->mm.pgd = get_free_page(); + if (!p->mm.pgd) { + return -1; + } + struct pt_regs * childregs = task_pt_regs (p); memzero ((ptr_t) childregs, sizeof (struct pt_regs)); memzero ((ptr_t) &p->cpu_context, sizeof (struct cpu_context)); @@ -26,7 +31,6 @@ int copy_process (ptr_t clone_flags, ptr_t fn, ptr_t arg, ptr_t stack) { *childregs = *cur_regs; childregs->regs[0] = 0; childregs->sp = stack + PAGE_SIZE; - p->stack = stack; } p->flags = clone_flags; p->priority = current->priority; @@ -48,12 +52,6 @@ int move_to_user_mode (ptr_t pc) { memzero ((ptr_t) regs, sizeof (*regs)); regs->pc = pc; regs->pstate = PSR_MODE_EL0t; - ptr_t stack = get_free_page ();//allocate new user stack - if (!stack) { - return -1; - } - regs->sp = stack + PAGE_SIZE; - current->stack = stack; return 0; } diff --git a/thorn/src/kernel/irq.c b/thorn/src/kernel/irq.c index b893bda..f4fc207 100644 --- a/thorn/src/kernel/irq.c +++ b/thorn/src/kernel/irq.c @@ -1,7 +1,7 @@ #include "kernel/irq.h" const char * entry_error_messages[] = { - "SYNC_INVALID_EL1t", "IRQ_INVALID_EL1t", "FIQ_INVALID_EL1t", "ERROR_INVALID_EL1T", "SYNC_INVALID_EL1h", "IRQ_INVALID_EL1h", "FIQ_INVALID_EL1h", "ERROR_INVALID_EL1h", "SYNC_INVALID_EL0_64", "IRQ_INVALID_EL0_64", "FIQ_INVALID_EL0_64", "ERROR_INVALID_EL0_64", "SYNC_INVALID_EL0_32", "IRQ_INVALID_EL0_32", "FIQ_INVALID_EL0_32", "ERROR_INVALID_EL0_32"}; + "SYNC_INVALID_EL1t", "IRQ_INVALID_EL1t", "FIQ_INVALID_EL1t", "ERROR_INVALID_EL1T", "SYNC_INVALID_EL1h", "IRQ_INVALID_EL1h", "FIQ_INVALID_EL1h", "ERROR_INVALID_EL1h", "SYNC_INVALID_EL0_64", "IRQ_INVALID_EL0_64", "FIQ_INVALID_EL0_64", "ERROR_INVALID_EL0_64", "SYNC_INVALID_EL0_32", "IRQ_INVALID_EL0_32", "FIQ_INVALID_EL0_32", "ERROR_INVALID_EL0_32", "SYNC_ERROR", "SYSCALL_ERROR"}; void enable_interrupt (unsigned int irq) { printf ("Interrupt pointer %p\r\n", irq); diff --git a/thorn/src/kernel/kernel.c b/thorn/src/kernel/kernel.c index 832b18a..59b6669 100644 --- a/thorn/src/kernel/kernel.c +++ b/thorn/src/kernel/kernel.c @@ -18,7 +18,7 @@ void multiplex_print (void * p, char c) { printc (c); - uart_send (c); + // uart_send (c); } void user_process1 (char * array) { diff --git a/thorn/src/kernel/sched.c b/thorn/src/kernel/sched.c index ff408dc..3cc9c1c 100644 --- a/thorn/src/kernel/sched.c +++ b/thorn/src/kernel/sched.c @@ -61,6 +61,7 @@ void switch_to (struct task_struct * next, int index) { } struct task_struct * prev = current; current = next; + set_pgd (next->mm.pgd); cpu_switch_to (prev, next); } @@ -87,13 +88,20 @@ void exit_process () { break; } } - if (current->stack) { - free_page (current->stack); - } preempt_enable (); schedule (); } +void kill_process () { + preempt_disable (); + for (int i = 0; i < NR_TASKS; i++) { + if (task[i] == current) { + task[i]->state = TASK_ZOMBIE; + break; + } + } + preempt_enable (); +} void task_init () { memzero ((ptr_t) current, sizeof (struct task_struct)); From 534240db464f31504afbefaeaeea983d6da1ff75 Mon Sep 17 00:00:00 2001 From: Max Streitberger Date: Thu, 4 Nov 2021 15:47:28 +0100 Subject: [PATCH 13/21] feat(mmu): WIP --- thorn/include/common/font.h | 7 +++++++ thorn/include/common/utils.h | 4 ++-- thorn/src/common/font.c | 14 ++++++++++++++ thorn/src/common/utils.S | 11 +++++++++-- thorn/src/kernel/entry.S | 3 +-- thorn/src/kernel/fork.c | 4 +++- thorn/src/kernel/kernel.c | 9 ++++++--- thorn/src/kernel/mmu.c | 6 +++--- thorn/src/kernel/sched.c | 15 ++++++++++++++- 9 files changed, 59 insertions(+), 14 deletions(-) diff --git a/thorn/include/common/font.h b/thorn/include/common/font.h index b732416..f203cf5 100644 --- a/thorn/include/common/font.h +++ b/thorn/include/common/font.h @@ -1,6 +1,8 @@ #ifndef _ROSE_C_FONT_H #define _ROSE_C_FONT_H +#ifndef __ASSEMBLER__ + #define FONT_SIZE 8 #define FONT_FACTOR 2 #define FONT_REAL_WIDTH (FONT_SIZE * FONT_FACTOR) @@ -32,6 +34,7 @@ static volatile color_t font_fg; const unsigned long long int * font (int c); void printc (char c); +void prints (char const * str); void printc_location (point_t point, char c); void putc_screen (void * p, char c); @@ -39,4 +42,8 @@ void putc_screen (void * p, char c); void font_set_normal (void); void font_set_error (void); +void test_print(); +void exit_print(); + #endif +#endif \ No newline at end of file diff --git a/thorn/include/common/utils.h b/thorn/include/common/utils.h index ae4222e..411746e 100644 --- a/thorn/include/common/utils.h +++ b/thorn/include/common/utils.h @@ -9,8 +9,8 @@ extern unsigned int get32 (unsigned long); extern int get_el (void); -extern void set_pgd(unsigned long pgd); +extern void set_pgd (unsigned long pgd); -extern unsigned long get_pgd(); +extern unsigned long get_pgd (void); #endif /*_ROSE_C_BOOT_H */ diff --git a/thorn/src/common/font.c b/thorn/src/common/font.c index 86addf5..a397708 100644 --- a/thorn/src/common/font.c +++ b/thorn/src/common/font.c @@ -191,6 +191,12 @@ void printc (char c) { } } +void prints(char const * str) { + while (*str) { + printc(*str++); + } +} + void font_set_normal (void) { font_fg = font_normal_fg; } @@ -201,3 +207,11 @@ void font_set_error (void) { void putc_screen (void * p, char c) { printc (c); } + +void test_print() { + prints("123454321\n\r"); +} + +void exit_print() { + prints("exit\n\r"); +} \ No newline at end of file diff --git a/thorn/src/common/utils.S b/thorn/src/common/utils.S index 1c3c8b6..4c4b84d 100644 --- a/thorn/src/common/utils.S +++ b/thorn/src/common/utils.S @@ -1,3 +1,5 @@ +#include "common/font.h" + .globl get_el get_el: mrs x0, CurrentEL @@ -22,10 +24,15 @@ delay: .globl set_pgd set_pgd: + bl test_print msr ttbr0_el1, x0 - tlbi vmalle1is - DSB ISH // ensure completion of TLB invalidation + bl test_print + //tlbi vmalle1is + bl test_print + DSB ISH // ensure completion of TLB invalidation + bl test_print isb + bl exit_print ret .globl get_pgd diff --git a/thorn/src/kernel/entry.S b/thorn/src/kernel/entry.S index 9c546c8..c5aa77f 100644 --- a/thorn/src/kernel/entry.S +++ b/thorn/src/kernel/entry.S @@ -9,7 +9,7 @@ mrs x1, esr_el1 mrs x2, elr_el1 bl show_invalid_entry_message - b exit_process + b err_hang .endm .macro ventry label @@ -191,7 +191,6 @@ el0_da: mrs x1, esr_el1 bl data_abort_el0 bl disable_irq - bl kill_process eret .globl ret_from_fork diff --git a/thorn/src/kernel/fork.c b/thorn/src/kernel/fork.c index dab1a81..1e04502 100644 --- a/thorn/src/kernel/fork.c +++ b/thorn/src/kernel/fork.c @@ -4,8 +4,10 @@ #include "kernel/entry.h" #include "kernel/mm.h" #include "kernel/sched.h" +#include "common/font.h" int copy_process (ptr_t clone_flags, ptr_t fn, ptr_t arg, ptr_t stack) { + prints ("copy process.kl\n\r"); preempt_disable (); struct task_struct * p; @@ -14,7 +16,7 @@ int copy_process (ptr_t clone_flags, ptr_t fn, ptr_t arg, ptr_t stack) { return -1; } - p->mm.pgd = get_free_page(); + p->mm.pgd = get_free_page (); if (!p->mm.pgd) { return -1; } diff --git a/thorn/src/kernel/kernel.c b/thorn/src/kernel/kernel.c index 59b6669..310fe11 100644 --- a/thorn/src/kernel/kernel.c +++ b/thorn/src/kernel/kernel.c @@ -17,8 +17,8 @@ #include "kernel/timer.h" void multiplex_print (void * p, char c) { - printc (c); - // uart_send (c); + // printc (c); + uart_send (c); } void user_process1 (char * array) { @@ -33,6 +33,7 @@ void user_process1 (char * array) { } void user_process () { + prints ("User process started.\n\r"); char buf[30] = {0}; tfp_sprintf (buf, "User process started\n\r"); call_sys_write (buf); @@ -60,7 +61,9 @@ void user_process () { } void kernel_process () { - // printf ("Kernel process started. EL %d\r\n", get_el ()); + prints ("Kernel process started.\n\r"); + printc ('0' + get_el ()); + prints ("\n\r"); int err = move_to_user_mode ((unsigned long) &user_process); if (err < 0) { printf ("Error while moving process to user mode\n\r"); diff --git a/thorn/src/kernel/mmu.c b/thorn/src/kernel/mmu.c index 49ab379..e30320c 100644 --- a/thorn/src/kernel/mmu.c +++ b/thorn/src/kernel/mmu.c @@ -134,9 +134,9 @@ void data_abort_el0 (ptr_t far, ptr_t esr) { byte_t level = esr & 0b11; esr &= 0b111111; - printf ("EL 0 - "); - printf ("FAR_EL1: %p - ", far); - printf ("ESR_EL1: %b\n\r", esr); + // printf ("EL 0 - "); + // printf ("FAR_EL1: %p - ", far); + // printf ("ESR_EL1: %b\n\r", esr); switch (type) { case 0b00:// Address size fault diff --git a/thorn/src/kernel/sched.c b/thorn/src/kernel/sched.c index 3cc9c1c..c5d6fec 100644 --- a/thorn/src/kernel/sched.c +++ b/thorn/src/kernel/sched.c @@ -4,6 +4,7 @@ #include "kernel/fork.h" #include "kernel/irq.h" #include "kernel/mm.h" +#include "common/debug.h" static struct task_struct init_task = INIT_TASK; struct task_struct * current = &(init_task); @@ -45,6 +46,7 @@ void _schedule (void) { } } } + CHECKPOINT switch_to (task[next], next); preempt_enable (); } @@ -61,7 +63,18 @@ void switch_to (struct task_struct * next, int index) { } struct task_struct * prev = current; current = next; - set_pgd (next->mm.pgd); + // set_pgd (next->mm.pgd); + CHECKPOINT + // asm("tlbi vmalle1is"); + // CHECKPOINT + asm volatile("msr ttbr0_el1, %0" + : + : "r"(next->mm.pgd)); + CHECKPOINT + asm("DSB ISH"); + CHECKPOINT + asm("isb"); + CHECKPOINT cpu_switch_to (prev, next); } From 9b346946ed5bb49fb47e72ebbaba075adad289aa Mon Sep 17 00:00:00 2001 From: Aaron Alef Date: Wed, 3 Nov 2021 16:37:49 +0100 Subject: [PATCH 14/21] feat(mmu): make all of non-kernel memory non-executable --- thorn/src/kernel/mmu.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/thorn/src/kernel/mmu.c b/thorn/src/kernel/mmu.c index e30320c..821db63 100644 --- a/thorn/src/kernel/mmu.c +++ b/thorn/src/kernel/mmu.c @@ -36,17 +36,18 @@ void init_pages () { PT_PAGE | // we have area in it mapped by pages PT_AF | // accessed flag PT_USER | // non-privileged + PT_NX | // non-executable PT_ISH | // inner shareable PT_MEM; // normal memory // identity L3 for (r = 0; r < 512; r++) - PTE0[r] = (unsigned long) (r * PAGESIZE) | // physical address - PT_PAGE | // map 4k - PT_AF | // accessed flag - PT_USER | // non-privileged - PT_ISH | // inner shareable - ((r < 0x80 || r >= data_page) ? PT_RW : PT_RO);// different for code and data + PTE0[r] = (unsigned long) (r * PAGESIZE) | // physical address + PT_PAGE | // map 4k + PT_AF | // accessed flag + PT_USER | // non-privileged + PT_ISH | // inner shareable + ((r < 0x80 || r >= data_page) ? PT_RW | PT_NX : PT_RO);// different for code and data } void init_mmu () { From 2c7ec97d110eac30d936f7952caf48b5cab0e25e Mon Sep 17 00:00:00 2001 From: Aaron Alef Date: Wed, 10 Nov 2021 16:17:31 +0100 Subject: [PATCH 15/21] refactor(mmu): misc changes for debugging; give ELR to data abort --- Makefile | 15 +-------------- thorn/include/common/font.h | 4 ++-- thorn/include/kernel/mmu.h | 3 ++- thorn/src/common/font.c | 14 +++++++------- thorn/src/common/utils.S | 8 ++------ thorn/src/kernel/entry.S | 7 +++++-- thorn/src/kernel/fork.c | 3 +-- thorn/src/kernel/kernel.c | 8 ++++---- thorn/src/kernel/mmu.c | 14 ++++++++++---- thorn/src/kernel/sched.c | 25 +++---------------------- 10 files changed, 37 insertions(+), 64 deletions(-) diff --git a/Makefile b/Makefile index e16cc6d..ab261a7 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ SERIAL_PORT_Darwin = /dev/$(shell ls /dev | grep usbserial | head -n 2 | tai SERIAL_PORT_ALT_Darwin = /dev/$(shell ls /dev | grep usbserial | head -n 1) # Building -BUILD_DEFAULT_TARGET = bulb +BUILD_DEFAULT_TARGET = thorn # Ensure make still works if someone creates a file named like follows: .PHONY: all build clean flash resend send reboot poweroff @@ -35,7 +35,6 @@ clean: rm -rf $(BUILD) *.img $(MAKE) -C chainloader clean $(MAKE) -C thorn clean - $(MAKE) -C bulb clean # Build the different OSes build: build-$(BUILD_DEFAULT_TARGET) @@ -48,9 +47,6 @@ build-chainloader: build-thorn: $(MAKE) -C thorn build -build-bulb: - $(MAKE) -C bulb build - # Mount boot partition of SD card onto set mount point to copy image onto it flash: flash-$(FLASH_DEFAULT_TARGET) @@ -60,9 +56,6 @@ flash-chainloader: flash-thorn: $(MAKE) -C thorn flash -flash-bulb: - $(MAKE) -C bulb flash - # Send kernel size + kernel setup-serial-Linux: stty -F $(SERIAL_PORT) $(BAUD_RATE) raw cs8 -ixoff -cstopb -parenb @@ -84,9 +77,6 @@ send-chainloader: setup-serial-$(HOST_OS) send-thorn: setup-serial-$(HOST_OS) $(MAKE) -C thorn send -send-bulb: setup-serial-$(HOST_OS) - $(MAKE) -C bulb send - # Set up screen on alternate serial port screen: screen $(SERIAL_PORT_ALT) $(BAUD_RATE) @@ -109,6 +99,3 @@ emulate-chainloader: emulate-thorn: $(MAKE) -C thorn emulate -emulate-bulb: - $(MAKE) -C bulb emulate - diff --git a/thorn/include/common/font.h b/thorn/include/common/font.h index f203cf5..426e898 100644 --- a/thorn/include/common/font.h +++ b/thorn/include/common/font.h @@ -42,8 +42,8 @@ void putc_screen (void * p, char c); void font_set_normal (void); void font_set_error (void); -void test_print(); -void exit_print(); +void test_print (); +void exit_print (); #endif #endif \ No newline at end of file diff --git a/thorn/include/kernel/mmu.h b/thorn/include/kernel/mmu.h index 169ac60..cda3ed2 100644 --- a/thorn/include/kernel/mmu.h +++ b/thorn/include/kernel/mmu.h @@ -11,6 +11,7 @@ #include "common/status_led.h" #include "kernel/mini_uart.h" #include "kernel/peripherals/base.h" +#include "kernel/sched.h" #define PAGESIZE 4096 @@ -45,7 +46,7 @@ static volatile unsigned int __attribute__ ((aligned (16))) buffer[32]; void init_pages (); void init_mmu (void); -void data_abort_el0 (ptr_t far, ptr_t esr); +void data_abort_el0 (ptr_t far, ptr_t esr, ptr_t elr); #endif #endif//_ROSE_MMU_H \ No newline at end of file diff --git a/thorn/src/common/font.c b/thorn/src/common/font.c index a397708..8f71609 100644 --- a/thorn/src/common/font.c +++ b/thorn/src/common/font.c @@ -191,9 +191,9 @@ void printc (char c) { } } -void prints(char const * str) { +void prints (char const * str) { while (*str) { - printc(*str++); + printc (*str++); } } @@ -208,10 +208,10 @@ void putc_screen (void * p, char c) { printc (c); } -void test_print() { - prints("123454321\n\r"); +void test_print () { + prints ("test\n\r"); } -void exit_print() { - prints("exit\n\r"); -} \ No newline at end of file +void exit_print () { + prints ("exit\n\r"); +} diff --git a/thorn/src/common/utils.S b/thorn/src/common/utils.S index 4c4b84d..018062d 100644 --- a/thorn/src/common/utils.S +++ b/thorn/src/common/utils.S @@ -24,13 +24,9 @@ delay: .globl set_pgd set_pgd: - bl test_print msr ttbr0_el1, x0 - bl test_print - //tlbi vmalle1is - bl test_print - DSB ISH // ensure completion of TLB invalidation - bl test_print +// tlbi vmalle1is + dsb ish // ensure completion of TLB invalidation isb bl exit_print ret diff --git a/thorn/src/kernel/entry.S b/thorn/src/kernel/entry.S index c5aa77f..4dd8c16 100644 --- a/thorn/src/kernel/entry.S +++ b/thorn/src/kernel/entry.S @@ -157,9 +157,11 @@ el0_irq: el0_sync: kernel_entry 0 - mrs x25, esr_el1 // read the syndrome register + mrs x25, esr_el1 // read the syndrome register lsr x24, x25, #ESR_ELx_EC_SHIFT // exception class - cmp x24, #ESR_ELx_EC_DABT_LOW + cmp x24, #ESR_ELx_EC_SVC64 // SVC in 64-bit state + b.eq el0_svc + cmp x24, #ESR_ELx_EC_DABT_LOW b.eq el0_da handle_invalid_entry 0, SYNC_ERROR @@ -189,6 +191,7 @@ el0_da: bl enable_irq mrs x0, far_el1 mrs x1, esr_el1 + mrs x2, elr_el1 bl data_abort_el0 bl disable_irq eret diff --git a/thorn/src/kernel/fork.c b/thorn/src/kernel/fork.c index 1e04502..49a49b8 100644 --- a/thorn/src/kernel/fork.c +++ b/thorn/src/kernel/fork.c @@ -1,13 +1,12 @@ #include "kernel/fork.h" +#include "common/font.h" #include "common/printf.h" #include "common/utils.h" #include "kernel/entry.h" #include "kernel/mm.h" #include "kernel/sched.h" -#include "common/font.h" int copy_process (ptr_t clone_flags, ptr_t fn, ptr_t arg, ptr_t stack) { - prints ("copy process.kl\n\r"); preempt_disable (); struct task_struct * p; diff --git a/thorn/src/kernel/kernel.c b/thorn/src/kernel/kernel.c index 310fe11..6698c38 100644 --- a/thorn/src/kernel/kernel.c +++ b/thorn/src/kernel/kernel.c @@ -17,8 +17,8 @@ #include "kernel/timer.h" void multiplex_print (void * p, char c) { - // printc (c); - uart_send (c); + printc (c); + // uart_send (c); } void user_process1 (char * array) { @@ -116,8 +116,8 @@ void kernel_main (int processor_id) { printf ("Hello, from processor %d in EL %d\n\r", processor_id, get_el ()); init_mmu (); - current_processor++; - while (current_processor != 4) {} + // current_processor++; + // while (current_processor != 4) {} switch (processor_id) { case 0: { diff --git a/thorn/src/kernel/mmu.c b/thorn/src/kernel/mmu.c index 821db63..3cb0a5d 100644 --- a/thorn/src/kernel/mmu.c +++ b/thorn/src/kernel/mmu.c @@ -130,14 +130,15 @@ void init_mmu () { LOG ("Set SCTLR flags and enable MMU"); } -void data_abort_el0 (ptr_t far, ptr_t esr) { +void data_abort_el0 (ptr_t far, ptr_t esr, ptr_t elr) { byte_t type = (esr >> 2) & 0b11; byte_t level = esr & 0b11; esr &= 0b111111; - // printf ("EL 0 - "); - // printf ("FAR_EL1: %p - ", far); - // printf ("ESR_EL1: %b\n\r", esr); + printf ("EL 0 - "); + printf ("FAR_EL1: %p - ", far); + printf ("ELR_EL1: %p - ", elr); + printf ("ESR_EL1: %b\r\n", esr); switch (type) { case 0b00:// Address size fault @@ -146,6 +147,11 @@ void data_abort_el0 (ptr_t far, ptr_t esr) { break; case 0b01:// Translation fault printf ("Translation fault during level %u of table walk on lookup of address %p.\r\n", level, far); + set_pgd ((unsigned long) &_end + TTBR_CNP); + // asm volatile("msr ttbr0_el1, %0" + // : + // : "r"((unsigned long) &_end + TTBR_CNP)); + LOG ("Successfully (?) updated TTBR"); break; case 0b10:// Access flag fault printf ("Access flag fault during level %u of table walk on lookup of address %p.\r\n", level, far); diff --git a/thorn/src/kernel/sched.c b/thorn/src/kernel/sched.c index c5d6fec..f0f07cc 100644 --- a/thorn/src/kernel/sched.c +++ b/thorn/src/kernel/sched.c @@ -1,10 +1,10 @@ #include "kernel/sched.h" +#include "common/debug.h" #include "common/printf.h" #include "common/utils.h" #include "kernel/fork.h" #include "kernel/irq.h" #include "kernel/mm.h" -#include "common/debug.h" static struct task_struct init_task = INIT_TASK; struct task_struct * current = &(init_task); @@ -21,7 +21,6 @@ void preempt_enable (void) { current->preempt_count--; } - void _schedule (void) { preempt_disable (); int next, c; @@ -46,7 +45,6 @@ void _schedule (void) { } } } - CHECKPOINT switch_to (task[next], next); preempt_enable (); } @@ -56,25 +54,19 @@ void schedule (void) { _schedule (); } - void switch_to (struct task_struct * next, int index) { if (current == next) { return; } struct task_struct * prev = current; current = next; - // set_pgd (next->mm.pgd); - CHECKPOINT - // asm("tlbi vmalle1is"); - // CHECKPOINT + // set_pgd (next->mm.pgd); + asm("tlbi vmalle1is"); asm volatile("msr ttbr0_el1, %0" : : "r"(next->mm.pgd)); - CHECKPOINT asm("DSB ISH"); - CHECKPOINT asm("isb"); - CHECKPOINT cpu_switch_to (prev, next); } @@ -105,17 +97,6 @@ void exit_process () { schedule (); } -void kill_process () { - preempt_disable (); - for (int i = 0; i < NR_TASKS; i++) { - if (task[i] == current) { - task[i]->state = TASK_ZOMBIE; - break; - } - } - preempt_enable (); -} - void task_init () { memzero ((ptr_t) current, sizeof (struct task_struct)); current->priority = 1; From b121473c8dec638ff24c10822a6730963f156384 Mon Sep 17 00:00:00 2001 From: Aaron Alef Date: Wed, 10 Nov 2021 17:12:04 +0100 Subject: [PATCH 16/21] chore: figure out mmu gets stuck in schedule --- thorn/include/common/font.h | 2 +- thorn/include/kernel/mm.h | 2 +- thorn/include/kernel/mmu.h | 1 + thorn/include/kernel/sched.h | 1 + thorn/src/kernel/boot.S | 19 ++++++++++--------- thorn/src/kernel/entry.S | 5 +++-- thorn/src/kernel/irq.c | 2 +- thorn/src/kernel/kernel.c | 11 ++++++----- thorn/src/kernel/mmu.c | 14 +++++++------- thorn/src/kernel/sched.c | 12 ++++++------ thorn/src/kernel/timer.c | 1 + 11 files changed, 38 insertions(+), 32 deletions(-) diff --git a/thorn/include/common/font.h b/thorn/include/common/font.h index 426e898..4cd6fdd 100644 --- a/thorn/include/common/font.h +++ b/thorn/include/common/font.h @@ -4,7 +4,7 @@ #ifndef __ASSEMBLER__ #define FONT_SIZE 8 -#define FONT_FACTOR 2 +#define FONT_FACTOR 3 #define FONT_REAL_WIDTH (FONT_SIZE * FONT_FACTOR) // Spacing between lines in pixels diff --git a/thorn/include/kernel/mm.h b/thorn/include/kernel/mm.h index d2f325a..642bc3e 100644 --- a/thorn/include/kernel/mm.h +++ b/thorn/include/kernel/mm.h @@ -11,7 +11,7 @@ #define PAGE_SIZE (1 << PAGE_SHIFT) #define SECTION_SIZE (1 << SECTION_SHIFT) -#define LOW_MEMORY (2 * SECTION_SIZE) +#define LOW_MEMORY (1 * SECTION_SIZE) #define HIGH_MEMORY 0x70000000 #define PAGING_MEMORY (HIGH_MEMORY - LOW_MEMORY) diff --git a/thorn/include/kernel/mmu.h b/thorn/include/kernel/mmu.h index cda3ed2..07c5c6e 100644 --- a/thorn/include/kernel/mmu.h +++ b/thorn/include/kernel/mmu.h @@ -9,6 +9,7 @@ #include "common/font.h" #include "common/logging.h" #include "common/status_led.h" +#include "kernel/irq.h" #include "kernel/mini_uart.h" #include "kernel/peripherals/base.h" #include "kernel/sched.h" diff --git a/thorn/include/kernel/sched.h b/thorn/include/kernel/sched.h index ab1c24d..a01b136 100644 --- a/thorn/include/kernel/sched.h +++ b/thorn/include/kernel/sched.h @@ -1,6 +1,7 @@ #ifndef _ROSE_K_SCHED_H #define _ROSE_K_SCHED_H +#include "common/font.h" #include "common/stddef.h" #define THREAD_CPU_CONTEXT 0// offset of cpu_context in task_struct diff --git a/thorn/src/kernel/boot.S b/thorn/src/kernel/boot.S index b83930e..50f40d2 100644 --- a/thorn/src/kernel/boot.S +++ b/thorn/src/kernel/boot.S @@ -21,16 +21,17 @@ init_bss: bl memzero adr x0, move_to_el1 - mov x1, #0xe0 - str x0, [x1] - mov x1, #0xe8 - str x0, [x1] - - mov x1, #0xf0 - str x0, [x1] - - sev +// mov x1, #0xe0 +// str x0, [x1] +// +// mov x1, #0xe8 +// str x0, [x1] +// +// mov x1, #0xf0 +// str x0, [x1] +// +// sev b move_to_el1 diff --git a/thorn/src/kernel/entry.S b/thorn/src/kernel/entry.S index 4dd8c16..b7bafbe 100644 --- a/thorn/src/kernel/entry.S +++ b/thorn/src/kernel/entry.S @@ -188,12 +188,13 @@ ret_from_syscall: kernel_exit 0 el0_da: - bl enable_irq + bl preempt_disable mrs x0, far_el1 mrs x1, esr_el1 mrs x2, elr_el1 bl data_abort_el0 - bl disable_irq + bl preempt_enable + bl disable_irq eret .globl ret_from_fork diff --git a/thorn/src/kernel/irq.c b/thorn/src/kernel/irq.c index f4fc207..2c95c0f 100644 --- a/thorn/src/kernel/irq.c +++ b/thorn/src/kernel/irq.c @@ -20,7 +20,7 @@ void assign_target (unsigned int irq, unsigned int cpu) { } void show_invalid_entry_message (int type, ptr_t esr, ptr_t address) { - printf ("Type %s, ESR: %p, address, %p\r\n", entry_error_messages[type], (void *) esr, (void *) address); + printf ("Type %s, ESR: %p, ELR: %p\r\n", entry_error_messages[type], (void *) esr, (void *) address); } void enable_interrupt_controller () { diff --git a/thorn/src/kernel/kernel.c b/thorn/src/kernel/kernel.c index 6698c38..a8bf6a1 100644 --- a/thorn/src/kernel/kernel.c +++ b/thorn/src/kernel/kernel.c @@ -33,7 +33,7 @@ void user_process1 (char * array) { } void user_process () { - prints ("User process started.\n\r"); + printf ("User process started.\n\r"); char buf[30] = {0}; tfp_sprintf (buf, "User process started\n\r"); call_sys_write (buf); @@ -73,10 +73,6 @@ void kernel_process () { void kernel_init (void) { uart_init (); init_printf (0, putc); - irq_vector_init (); - timer_init (); - enable_interrupt_controller (); - enable_irq (); task_init (); // Turn status led OFF and power led ON @@ -119,6 +115,11 @@ void kernel_main (int processor_id) { // current_processor++; // while (current_processor != 4) {} + irq_vector_init (); + timer_init (); + enable_interrupt_controller (); + enable_irq (); + switch (processor_id) { case 0: { int res = copy_process (PF_KTHREAD, (unsigned long) &kernel_process, 0, 0); diff --git a/thorn/src/kernel/mmu.c b/thorn/src/kernel/mmu.c index 3cb0a5d..d4c61f4 100644 --- a/thorn/src/kernel/mmu.c +++ b/thorn/src/kernel/mmu.c @@ -135,9 +135,8 @@ void data_abort_el0 (ptr_t far, ptr_t esr, ptr_t elr) { byte_t level = esr & 0b11; esr &= 0b111111; - printf ("EL 0 - "); - printf ("FAR_EL1: %p - ", far); printf ("ELR_EL1: %p - ", elr); + printf ("FAR_EL1: %p - ", far); printf ("ESR_EL1: %b\r\n", esr); switch (type) { @@ -147,11 +146,12 @@ void data_abort_el0 (ptr_t far, ptr_t esr, ptr_t elr) { break; case 0b01:// Translation fault printf ("Translation fault during level %u of table walk on lookup of address %p.\r\n", level, far); - set_pgd ((unsigned long) &_end + TTBR_CNP); - // asm volatile("msr ttbr0_el1, %0" - // : - // : "r"((unsigned long) &_end + TTBR_CNP)); - LOG ("Successfully (?) updated TTBR"); + asm volatile("msr ttbr0_el1, %0" + : + : "r"((unsigned long) &_end + TTBR_CNP)); + // asm volatile("dsb ish"); + // asm volatile("isb"); + enable_irq (); break; case 0b10:// Access flag fault printf ("Access flag fault during level %u of table walk on lookup of address %p.\r\n", level, far); diff --git a/thorn/src/kernel/sched.c b/thorn/src/kernel/sched.c index f0f07cc..5a8e469 100644 --- a/thorn/src/kernel/sched.c +++ b/thorn/src/kernel/sched.c @@ -26,6 +26,7 @@ void _schedule (void) { int next, c; struct task_struct * p; while (1) { + printc ('-'); c = -1; next = 0; for (int i = 0; i < NR_TASKS; i++) { @@ -61,12 +62,11 @@ void switch_to (struct task_struct * next, int index) { struct task_struct * prev = current; current = next; // set_pgd (next->mm.pgd); - asm("tlbi vmalle1is"); - asm volatile("msr ttbr0_el1, %0" - : - : "r"(next->mm.pgd)); - asm("DSB ISH"); - asm("isb"); + // asm volatile("msr ttbr0_el1, %0" + // : + // : "r"(next->mm.pgd)); + // asm("DSB ISH"); + // asm("isb"); cpu_switch_to (prev, next); } diff --git a/thorn/src/kernel/timer.c b/thorn/src/kernel/timer.c index 0fe4556..79be217 100644 --- a/thorn/src/kernel/timer.c +++ b/thorn/src/kernel/timer.c @@ -15,6 +15,7 @@ void timer_init (void) { void handle_timer_irq (void) { toggle_led (STATUS_LED); + printc ('|'); curVal += interval; put32 (TIMER_C1, curVal); From dee35633f98f9e5341d23dcfc693a4cbede97bb5 Mon Sep 17 00:00:00 2001 From: Aaron Alef Date: Thu, 11 Nov 2021 10:20:01 +0100 Subject: [PATCH 17/21] WIP: figure out why user_process starts with sp = 0 --- thorn/src/kernel/fork.c | 2 +- thorn/src/kernel/kernel.c | 1 + thorn/src/kernel/sched.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/thorn/src/kernel/fork.c b/thorn/src/kernel/fork.c index 49a49b8..4da01af 100644 --- a/thorn/src/kernel/fork.c +++ b/thorn/src/kernel/fork.c @@ -37,7 +37,7 @@ int copy_process (ptr_t clone_flags, ptr_t fn, ptr_t arg, ptr_t stack) { p->priority = current->priority; p->state = TASK_RUNNING; p->counter = p->priority; - p->preempt_count = 1;//disable preemtion until schedule_tail + p->preempt_count = 1;//disable preemption until schedule_tail p->cpu_context.pc = (ptr_t) ret_from_fork; p->cpu_context.sp = (ptr_t) childregs; diff --git a/thorn/src/kernel/kernel.c b/thorn/src/kernel/kernel.c index a8bf6a1..c3f3425 100644 --- a/thorn/src/kernel/kernel.c +++ b/thorn/src/kernel/kernel.c @@ -119,6 +119,7 @@ void kernel_main (int processor_id) { timer_init (); enable_interrupt_controller (); enable_irq (); + CHECKPOINT switch (processor_id) { case 0: { diff --git a/thorn/src/kernel/sched.c b/thorn/src/kernel/sched.c index 5a8e469..3795bd7 100644 --- a/thorn/src/kernel/sched.c +++ b/thorn/src/kernel/sched.c @@ -23,7 +23,7 @@ void preempt_enable (void) { void _schedule (void) { preempt_disable (); - int next, c; + long next, c; struct task_struct * p; while (1) { printc ('-'); From 83813b77f03f29bfd464f17466457e357ac5ef85 Mon Sep 17 00:00:00 2001 From: Aaron Alef Date: Thu, 11 Nov 2021 14:41:06 +0100 Subject: [PATCH 18/21] WIP: try to figure out why user_process hangs immediately --- thorn/include/kernel/irq.h | 2 +- thorn/src/common/utils.S | 2 +- thorn/src/kernel/entry.S | 22 ++++++++++++---------- thorn/src/kernel/irq.c | 4 ++-- thorn/src/kernel/kernel.c | 3 +++ thorn/src/kernel/mmu.c | 4 ++-- thorn/src/kernel/sched.c | 12 ++++++++---- 7 files changed, 29 insertions(+), 20 deletions(-) diff --git a/thorn/include/kernel/irq.h b/thorn/include/kernel/irq.h index d95cc0b..47652e8 100644 --- a/thorn/include/kernel/irq.h +++ b/thorn/include/kernel/irq.h @@ -13,7 +13,7 @@ void enable_interrupt_controller (void); -void show_invalid_entry_message (int type, ptr_t esr, ptr_t address); +void show_invalid_entry_message (int type, ptr_t esr, ptr_t elr, ptr_t far); void irq_vector_init (void); diff --git a/thorn/src/common/utils.S b/thorn/src/common/utils.S index 018062d..976cc8b 100644 --- a/thorn/src/common/utils.S +++ b/thorn/src/common/utils.S @@ -25,7 +25,7 @@ delay: .globl set_pgd set_pgd: msr ttbr0_el1, x0 -// tlbi vmalle1is +// tlbi vmalle1is // Crashes CPU dsb ish // ensure completion of TLB invalidation isb bl exit_print diff --git a/thorn/src/kernel/entry.S b/thorn/src/kernel/entry.S index b7bafbe..07606ed 100644 --- a/thorn/src/kernel/entry.S +++ b/thorn/src/kernel/entry.S @@ -8,6 +8,7 @@ mov x0, #\type mrs x1, esr_el1 mrs x2, elr_el1 + mrs x3, far_el1 bl show_invalid_entry_message b err_hang .endm @@ -92,19 +93,19 @@ vectors: ventry error_invalid_el1t // Error EL1t ventry sync_invalid_el1h // Synchronous EL1h - ventry el1_irq // IRQ EL1h + ventry el1_irq // IRQ EL1h ventry fiq_invalid_el1h // FIQ EL1h ventry error_invalid_el1h // Error EL1h - ventry el0_sync // Synchronous 64-bit EL0 - ventry el0_irq // IRQ 64-bit EL0 + ventry el0_sync // Synchronous 64-bit EL0 + ventry el0_irq // IRQ 64-bit EL0 ventry fiq_invalid_el0_64 // FIQ 64-bit EL0 - ventry error_invalid_el0_64 // Error 64-bit EL0 + ventry error_invalid_el0_64 // Error 64-bit EL0 ventry sync_invalid_el0_32 // Synchronous 32-bit EL0 ventry irq_invalid_el0_32 // IRQ 32-bit EL0 ventry fiq_invalid_el0_32 // FIQ 32-bit EL0 - ventry error_invalid_el0_32 // Error 32-bit EL0 + ventry error_invalid_el0_32 // Error 32-bit EL0 sync_invalid_el1t: handle_invalid_entry 1, SYNC_INVALID_EL1t @@ -156,6 +157,7 @@ el0_irq: kernel_exit 0 el0_sync: + bl test_print kernel_entry 0 mrs x25, esr_el1 // read the syndrome register lsr x24, x25, #ESR_ELx_EC_SHIFT // exception class @@ -170,15 +172,15 @@ scno .req x26 // syscall number stbl .req x27 // syscall table pointer el0_svc: - adr stbl, sys_call_table // load syscall table pointer - uxtw scno, w8 // syscall number in w8 + adr stbl, sys_call_table // load syscall table pointer + uxtw scno, w8 // syscall number in w8 mov sc_nr, #__NR_syscalls bl enable_irq - cmp scno, sc_nr // check upper syscall limit + cmp scno, sc_nr // check upper syscall limit b.hs ni_sys - ldr x16, [stbl, scno, lsl #3] // address in the syscall table - blr x16 // call sys_* routine + ldr x16, [stbl, scno, lsl #3] // address in the syscall table + blr x16 // call sys_* routine b ret_from_syscall ni_sys: handle_invalid_entry 0, SYSCALL_ERROR diff --git a/thorn/src/kernel/irq.c b/thorn/src/kernel/irq.c index 2c95c0f..c182b39 100644 --- a/thorn/src/kernel/irq.c +++ b/thorn/src/kernel/irq.c @@ -19,8 +19,8 @@ void assign_target (unsigned int irq, unsigned int cpu) { put32 (targetRegister, get32 (targetRegister) | (1 << 8)); } -void show_invalid_entry_message (int type, ptr_t esr, ptr_t address) { - printf ("Type %s, ESR: %p, ELR: %p\r\n", entry_error_messages[type], (void *) esr, (void *) address); +void show_invalid_entry_message (int type, ptr_t esr, ptr_t elr, ptr_t far) { + printf ("Type %s, FAR: %p, ESR: %p, ELR: %p\r\n", entry_error_messages[type], (void *) far, (void *) (esr >> ESR_ELx_EC_SHIFT), (void *) elr); } void enable_interrupt_controller () { diff --git a/thorn/src/kernel/kernel.c b/thorn/src/kernel/kernel.c index c3f3425..660997b 100644 --- a/thorn/src/kernel/kernel.c +++ b/thorn/src/kernel/kernel.c @@ -68,6 +68,9 @@ void kernel_process () { if (err < 0) { printf ("Error while moving process to user mode\n\r"); } + // Explicitly remove this task..? + --nr_tasks; + current->state = TASK_ZOMBIE; } void kernel_init (void) { diff --git a/thorn/src/kernel/mmu.c b/thorn/src/kernel/mmu.c index d4c61f4..79505ab 100644 --- a/thorn/src/kernel/mmu.c +++ b/thorn/src/kernel/mmu.c @@ -149,8 +149,8 @@ void data_abort_el0 (ptr_t far, ptr_t esr, ptr_t elr) { asm volatile("msr ttbr0_el1, %0" : : "r"((unsigned long) &_end + TTBR_CNP)); - // asm volatile("dsb ish"); - // asm volatile("isb"); + asm volatile("dsb ish"); + asm volatile("isb"); enable_irq (); break; case 0b10:// Access flag fault diff --git a/thorn/src/kernel/sched.c b/thorn/src/kernel/sched.c index 3795bd7..6865db4 100644 --- a/thorn/src/kernel/sched.c +++ b/thorn/src/kernel/sched.c @@ -23,13 +23,17 @@ void preempt_enable (void) { void _schedule (void) { preempt_disable (); - long next, c; + long next, c, cur; struct task_struct * p; while (1) { printc ('-'); + printc ('0' + nr_tasks); c = -1; next = 0; + cur; for (int i = 0; i < NR_TASKS; i++) { + if (task[i] == current) + cur = i; p = task[i]; if (p && p->state == TASK_RUNNING && p->counter > c) { c = p->counter; @@ -37,6 +41,7 @@ void _schedule (void) { } } if (c) { + printc ('0' + cur); break; } for (int i = 0; i < NR_TASKS; i++) { @@ -61,12 +66,11 @@ void switch_to (struct task_struct * next, int index) { } struct task_struct * prev = current; current = next; - // set_pgd (next->mm.pgd); // asm volatile("msr ttbr0_el1, %0" // : // : "r"(next->mm.pgd)); - // asm("DSB ISH"); - // asm("isb"); + // asm volatile("DSB ISH"); + // asm volatile ("isb"); cpu_switch_to (prev, next); } From c1b826e27f67268e0ce8386eb3c07f1ea4979b8c Mon Sep 17 00:00:00 2001 From: Aaron Alef Date: Thu, 11 Nov 2021 15:21:42 +0100 Subject: [PATCH 19/21] refactor(mmu): right now, everything runs fine User and kernel space both use the same, 1-to-1 mapped page tables --- thorn/include/common/font.h | 1 - thorn/src/common/font.c | 6 +----- thorn/src/common/utils.S | 1 - thorn/src/kernel/entry.S | 1 - thorn/src/kernel/fork.c | 6 +++--- thorn/src/kernel/irq.c | 2 +- thorn/src/kernel/kernel.c | 8 +------- thorn/src/kernel/sched.c | 3 --- thorn/src/kernel/timer.c | 1 - 9 files changed, 6 insertions(+), 23 deletions(-) diff --git a/thorn/include/common/font.h b/thorn/include/common/font.h index 4cd6fdd..89b011b 100644 --- a/thorn/include/common/font.h +++ b/thorn/include/common/font.h @@ -43,7 +43,6 @@ void font_set_normal (void); void font_set_error (void); void test_print (); -void exit_print (); #endif #endif \ No newline at end of file diff --git a/thorn/src/common/font.c b/thorn/src/common/font.c index 8f71609..a093572 100644 --- a/thorn/src/common/font.c +++ b/thorn/src/common/font.c @@ -209,9 +209,5 @@ void putc_screen (void * p, char c) { } void test_print () { - prints ("test\n\r"); -} - -void exit_print () { - prints ("exit\n\r"); + prints ("test\r\n"); } diff --git a/thorn/src/common/utils.S b/thorn/src/common/utils.S index 976cc8b..d6a9596 100644 --- a/thorn/src/common/utils.S +++ b/thorn/src/common/utils.S @@ -28,7 +28,6 @@ set_pgd: // tlbi vmalle1is // Crashes CPU dsb ish // ensure completion of TLB invalidation isb - bl exit_print ret .globl get_pgd diff --git a/thorn/src/kernel/entry.S b/thorn/src/kernel/entry.S index 07606ed..e37bd6c 100644 --- a/thorn/src/kernel/entry.S +++ b/thorn/src/kernel/entry.S @@ -157,7 +157,6 @@ el0_irq: kernel_exit 0 el0_sync: - bl test_print kernel_entry 0 mrs x25, esr_el1 // read the syndrome register lsr x24, x25, #ESR_ELx_EC_SHIFT // exception class diff --git a/thorn/src/kernel/fork.c b/thorn/src/kernel/fork.c index 4da01af..8f95645 100644 --- a/thorn/src/kernel/fork.c +++ b/thorn/src/kernel/fork.c @@ -50,9 +50,9 @@ int copy_process (ptr_t clone_flags, ptr_t fn, ptr_t arg, ptr_t stack) { int move_to_user_mode (ptr_t pc) { struct pt_regs * regs = task_pt_regs (current); - memzero ((ptr_t) regs, sizeof (*regs)); - regs->pc = pc; - regs->pstate = PSR_MODE_EL0t; + regs->pc = pc; + regs->pstate = PSR_MODE_EL0t; + regs->sp = 2 * PAGE_SIZE; return 0; } diff --git a/thorn/src/kernel/irq.c b/thorn/src/kernel/irq.c index c182b39..98a4239 100644 --- a/thorn/src/kernel/irq.c +++ b/thorn/src/kernel/irq.c @@ -20,7 +20,7 @@ void assign_target (unsigned int irq, unsigned int cpu) { } void show_invalid_entry_message (int type, ptr_t esr, ptr_t elr, ptr_t far) { - printf ("Type %s, FAR: %p, ESR: %p, ELR: %p\r\n", entry_error_messages[type], (void *) far, (void *) (esr >> ESR_ELx_EC_SHIFT), (void *) elr); + printf ("Type %s, FAR: %p, ESR: %p, ELR: %p\r\n", entry_error_messages[type], (void *) far, (void *) (esr >> 0), (void *) elr); } void enable_interrupt_controller () { diff --git a/thorn/src/kernel/kernel.c b/thorn/src/kernel/kernel.c index 660997b..cc95c6d 100644 --- a/thorn/src/kernel/kernel.c +++ b/thorn/src/kernel/kernel.c @@ -33,7 +33,6 @@ void user_process1 (char * array) { } void user_process () { - printf ("User process started.\n\r"); char buf[30] = {0}; tfp_sprintf (buf, "User process started\n\r"); call_sys_write (buf); @@ -61,16 +60,11 @@ void user_process () { } void kernel_process () { - prints ("Kernel process started.\n\r"); - printc ('0' + get_el ()); - prints ("\n\r"); + printf ("Kernel process started.\n\r"); int err = move_to_user_mode ((unsigned long) &user_process); if (err < 0) { printf ("Error while moving process to user mode\n\r"); } - // Explicitly remove this task..? - --nr_tasks; - current->state = TASK_ZOMBIE; } void kernel_init (void) { diff --git a/thorn/src/kernel/sched.c b/thorn/src/kernel/sched.c index 6865db4..79fb818 100644 --- a/thorn/src/kernel/sched.c +++ b/thorn/src/kernel/sched.c @@ -26,8 +26,6 @@ void _schedule (void) { long next, c, cur; struct task_struct * p; while (1) { - printc ('-'); - printc ('0' + nr_tasks); c = -1; next = 0; cur; @@ -41,7 +39,6 @@ void _schedule (void) { } } if (c) { - printc ('0' + cur); break; } for (int i = 0; i < NR_TASKS; i++) { diff --git a/thorn/src/kernel/timer.c b/thorn/src/kernel/timer.c index 79be217..0fe4556 100644 --- a/thorn/src/kernel/timer.c +++ b/thorn/src/kernel/timer.c @@ -15,7 +15,6 @@ void timer_init (void) { void handle_timer_irq (void) { toggle_led (STATUS_LED); - printc ('|'); curVal += interval; put32 (TIMER_C1, curVal); From 735eb1b3e231c496f54327bb8aaa164b9d70d1b3 Mon Sep 17 00:00:00 2001 From: Aaron Alef Date: Tue, 14 Dec 2021 14:26:04 +0100 Subject: [PATCH 20/21] fix(irq): move irq init into kernel_init --- thorn/src/kernel/kernel.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/thorn/src/kernel/kernel.c b/thorn/src/kernel/kernel.c index cc95c6d..15d7abf 100644 --- a/thorn/src/kernel/kernel.c +++ b/thorn/src/kernel/kernel.c @@ -91,6 +91,11 @@ void kernel_init (void) { printf ("Height resolution: %d\r\n", get_fb_info ()->virtual_height); } } + irq_vector_init (); + timer_init (); + enable_interrupt_controller (); + enable_irq (); + init_pages (); LOG ("Initialisation done"); @@ -112,10 +117,6 @@ void kernel_main (int processor_id) { // current_processor++; // while (current_processor != 4) {} - irq_vector_init (); - timer_init (); - enable_interrupt_controller (); - enable_irq (); CHECKPOINT switch (processor_id) { From 3bcd28b0067328c7ae831aa91963d543ac63a99d Mon Sep 17 00:00:00 2001 From: Aaron Alef Date: Tue, 14 Dec 2021 14:29:10 +0100 Subject: [PATCH 21/21] refactor(mmu): on data abort, kill offending process --- thorn/src/kernel/mmu.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/thorn/src/kernel/mmu.c b/thorn/src/kernel/mmu.c index 79505ab..4d74945 100644 --- a/thorn/src/kernel/mmu.c +++ b/thorn/src/kernel/mmu.c @@ -142,24 +142,16 @@ void data_abort_el0 (ptr_t far, ptr_t esr, ptr_t elr) { switch (type) { case 0b00:// Address size fault printf ("Address size fault during level %u of table walk on lookup of address %p.\r\n", level, far); - // exit_process (); break; case 0b01:// Translation fault printf ("Translation fault during level %u of table walk on lookup of address %p.\r\n", level, far); - asm volatile("msr ttbr0_el1, %0" - : - : "r"((unsigned long) &_end + TTBR_CNP)); - asm volatile("dsb ish"); - asm volatile("isb"); - enable_irq (); break; case 0b10:// Access flag fault printf ("Access flag fault during level %u of table walk on lookup of address %p.\r\n", level, far); - // exit_process (); break; case 0b11:// Permission fault printf ("Permission fault during level %u of table walk on lookup of address %p.\r\n", level, far); - // exit_process (); break; } + exit_process (); } \ No newline at end of file