Created
June 5, 2020 03:07
-
-
Save nuta/6d636d2a5ca76fc77f0a433e6dabfe37 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/Kconfig b/Kconfig | |
index 30b56ec..46efaac 100644 | |
--- a/Kconfig | |
+++ b/Kconfig | |
@@ -4,6 +4,8 @@ choice | |
prompt "Target CPU architecture" | |
config ARCH_X64 | |
bool "x86_64" | |
+ config ARCH_ARM64 | |
+ bool "Raspberry Pi 3 (AArch64)" | |
config ARCH_ARM | |
bool "micro:bit (ARM)" | |
endchoice | |
diff --git a/kernel/arch/arm64/Kconfig b/kernel/arch/arm64/Kconfig | |
new file mode 100644 | |
index 0000000..1da9eb2 | |
--- /dev/null | |
+++ b/kernel/arch/arm64/Kconfig | |
@@ -0,0 +1,8 @@ | |
+menu "ARM64 Options" | |
+ depends on ARCH_ARM64 | |
+ | |
+ config ARCH | |
+ string | |
+ default "arm64" | |
+ | |
+endmenu | |
diff --git a/kernel/arch/arm64/arch.h b/kernel/arch/arm64/arch.h | |
new file mode 100644 | |
index 0000000..26b3778 | |
--- /dev/null | |
+++ b/kernel/arch/arm64/arch.h | |
@@ -0,0 +1,52 @@ | |
+#ifndef __ARCH_H__ | |
+#define __ARCH_H__ | |
+ | |
+#include <types.h> | |
+ | |
+#define TICK_HZ 1000 | |
+#define IRQ_MAX 32 | |
+#define STRAIGHT_MAP_ADDR 0 // Unused. | |
+#define STRAIGHT_MAP_END 0 // Unused. | |
+ | |
+struct vm { | |
+}; | |
+ | |
+struct arch_task { | |
+ void *stack_bottom; | |
+ vaddr_t stack; | |
+}; | |
+ | |
+static inline void *from_paddr(paddr_t addr) { | |
+ return (void *) addr; | |
+} | |
+ | |
+static inline paddr_t into_paddr(void *addr) { | |
+ return (vaddr_t) addr; | |
+} | |
+ | |
+static inline bool is_kernel_addr_range(vaddr_t base, size_t len) { | |
+ return false; | |
+} | |
+ | |
+static inline bool is_kernel_paddr(paddr_t paddr) { | |
+ return false; | |
+} | |
+ | |
+static inline int mp_self(void) { | |
+ return 0; | |
+} | |
+ | |
+static inline bool mp_is_bsp(void) { | |
+ return mp_self() == 0; | |
+} | |
+ | |
+ | |
+struct arch_cpuvar { | |
+}; | |
+ | |
+extern struct cpuvar cpuvar; | |
+static inline struct cpuvar *get_cpuvar(void) { | |
+ return &cpuvar; | |
+} | |
+ | |
+#endif | |
diff --git a/kernel/arch/arm64/boot.S b/kernel/arch/arm64/boot.S | |
new file mode 100644 | |
index 0000000..61cc844 | |
--- /dev/null | |
+++ b/kernel/arch/arm64/boot.S | |
@@ -0,0 +1,51 @@ | |
+/* | |
+ * Copyright (C) 2018 bzt (bztsrc@github) | |
+ * | |
+ * Permission is hereby granted, free of charge, to any person | |
+ * obtaining a copy of this software and associated documentation | |
+ * files (the "Software"), to deal in the Software without | |
+ * restriction, including without limitation the rights to use, copy, | |
+ * modify, merge, publish, distribute, sublicense, and/or sell copies | |
+ * of the Software, and to permit persons to whom the Software is | |
+ * furnished to do so, subject to the following conditions: | |
+ * | |
+ * The above copyright notice and this permission notice shall be | |
+ * included in all copies or substantial portions of the Software. | |
+ * | |
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
+ * DEALINGS IN THE SOFTWARE. | |
+ * | |
+ */ | |
+ | |
+.section ".boot", "ax" | |
+.global boot | |
+boot: | |
+ // read cpu id, stop slave cores | |
+ mrs x1, mpidr_el1 | |
+ and x1, x1, #3 | |
+ cbz x1, 2f | |
+ // cpu id > 0, stop | |
+1: wfe | |
+ b 1b | |
+2: // cpu id == 0 | |
+ | |
+ // set stack before our code | |
+ ldr x1, =__stack | |
+ mov sp, x1 | |
+ | |
+3: | |
+ bl arm64_init | |
+ b 3b | |
+ | |
+.rodata | |
+.align 12 // 2^12 = 4096 | |
+.global __bootelf | |
+__bootelf: | |
+ .incbin BOOTELF_PATH | |
+.align 12 // 2^12 = 4096 | |
diff --git a/kernel/arch/arm64/build.mk b/kernel/arch/arm64/build.mk | |
new file mode 100644 | |
index 0000000..548b426 | |
--- /dev/null | |
+++ b/kernel/arch/arm64/build.mk | |
@@ -0,0 +1,20 @@ | |
+obj-y += boot.o init.o vm.o mp.o task.o switch.o peripherals.o interrupt.o | |
+ | |
+QEMU ?= qemu-system-aarch64 | |
+ | |
+CFLAGS += --target=aarch64-none-eabi -mcpu=cortex-a53 | |
+LDFLAGS += | |
+ | |
+QEMUFLAGS += -M raspi3 -serial mon:stdio | |
+QEMUFLAGS += $(if $(GUI),,-nographic) | |
+QEMUFLAGS += $(if $(GDB),-S -s,) | |
+ | |
+.PHONY: run | |
+run: $(BUILD_DIR)/resea.hex | |
+ $(QEMU) $(QEMUFLAGS) -device loader,file=$< | |
+ | |
+.PHONY: hex | |
+hex: $(BUILD_DIR)/resea.hex | |
+ | |
+$(BUILD_DIR)/resea.hex: $(kernel_image) | |
+ $(OBJCOPY) -Oihex $< $@ | |
diff --git a/kernel/arch/arm64/init.c b/kernel/arch/arm64/init.c | |
new file mode 100644 | |
index 0000000..88375aa | |
--- /dev/null | |
+++ b/kernel/arch/arm64/init.c | |
@@ -0,0 +1,20 @@ | |
+#include <types.h> | |
+#include <main.h> | |
+#include <printk.h> | |
+#include "peripherals.h" | |
+ | |
+void arch_idle(void) { | |
+ while (true) { | |
+ __asm__ __volatile__("wfi"); | |
+ } | |
+} | |
+ | |
+void arm64_init(void) { | |
+ arm_peripherals_init(); | |
+ kmain(); | |
+ | |
+ PANIC("kmain returned"); | |
+ for (;;) { | |
+ halt(); | |
+ } | |
+} | |
diff --git a/kernel/arch/arm64/interrupt.c b/kernel/arch/arm64/interrupt.c | |
new file mode 100644 | |
index 0000000..228d12d | |
--- /dev/null | |
+++ b/kernel/arch/arm64/interrupt.c | |
@@ -0,0 +1,26 @@ | |
+#include <types.h> | |
+#include <task.h> | |
+#include <printk.h> | |
+ | |
+void nmi_handler(void) { | |
+ PANIC("hard reset"); | |
+} | |
+ | |
+void hard_reset_handler(void) { | |
+ PANIC("hard reset"); | |
+} | |
+void unexpected_handler(void) { | |
+ PANIC("unexpected exception"); | |
+} | |
+ | |
+void irq_handler(void) { | |
+// handle_irq(irq); | |
+} | |
+ | |
+void arch_enable_irq(unsigned irq){ | |
+ // TODO: | |
+} | |
+ | |
+void arch_disable_irq(unsigned irq) { | |
+ // TODO: | |
+} | |
diff --git a/kernel/arch/arm64/kernel.ld b/kernel/arch/arm64/kernel.ld | |
new file mode 100644 | |
index 0000000..273b999 | |
--- /dev/null | |
+++ b/kernel/arch/arm64/kernel.ld | |
@@ -0,0 +1,76 @@ | |
+OUTPUT_FORMAT("elf64-x86-64"); | |
+ENTRY(boot); | |
+ | |
+/* LMA_OFFSET = 0xffff800000000000; */ | |
+LMA_OFFSET = 0; | |
+KERNEL_BOOT_ADDR = 0x80000; | |
+KERNEL_BASE_ADDR = 0x80000; | |
+/* KERNEL_BASE_ADDR = 0xffff800000100000; */ | |
+ | |
+PHDRS { | |
+ boot PT_LOAD FLAGS(5); /* flags = rx */ | |
+ text PT_LOAD FLAGS(5); /* flags = rx */ | |
+ data PT_LOAD FLAGS(6); /* flags = rw */ | |
+} | |
+ | |
+SECTIONS { | |
+ . = KERNEL_BOOT_ADDR; | |
+ __kernel_image = .; /* paddr_t */ | |
+ .boot : AT(KERNEL_BOOT_ADDR) { | |
+ KEEP(*(.boot)); | |
+ } :boot | |
+ | |
+ . = KERNEL_BASE_ADDR + SIZEOF(.boot); | |
+ | |
+ .text : AT(ADDR(.text) - LMA_OFFSET) ALIGN(8) { | |
+ *(.text); | |
+ *(.text.*); | |
+ } :text | |
+ | |
+ .rodata : AT(ADDR(.rodata) - LMA_OFFSET) ALIGN(8) { | |
+ *(.rodata); | |
+ *(.rodata.*); | |
+ } :text | |
+ | |
+ .data : AT(ADDR(.data) - LMA_OFFSET) ALIGN(8) { | |
+ *(.data); | |
+ *(.data.*); | |
+ } :data | |
+ | |
+ .bss : AT(ADDR(.bss) - LMA_OFFSET) ALIGN(8) { | |
+ __bss = .; | |
+ *(.bss); | |
+ *(.bss.*); | |
+ __bss_end = .; | |
+ } :data | |
+ | |
+ . = ALIGN(4096); | |
+ __kernel_image_end = . - KERNEL_BASE_ADDR + KERNEL_BOOT_ADDR; /* paddr_t */ | |
+ | |
+ . = 0x1000000; | |
+ __kernel_data = .; /* paddr_t */ | |
+ | |
+ /* CPU variables and boot stacks (paddr_t). */ | |
+ . = ALIGN(4096); | |
+ __cpuvar_base = .; | |
+ . += 0x4000 * 16; /* CPUVAR_SIZE_MAX * CPU_NUM_MAX */ | |
+ __boot_stack_base = .; | |
+ . += 0x1000 * 16; /* PAGE_SIZE * CPU_NUM_MAX */ | |
+ | |
+ /* Kernel Heap (vaddr_t). */ | |
+ . = ALIGN(4096); | |
+ . += LMA_OFFSET; | |
+ __kernel_heap = .; | |
+ . = LMA_OFFSET + 0x3000000; | |
+ __kernel_heap_end = .; | |
+ | |
+ . = ALIGN(4096); | |
+ __kernel_data_end = . - LMA_OFFSET; /* paddr_t */ | |
+ | |
+ /* A temporary page used internally by kernel (virtual address). */ | |
+ __temp_page = 0xffff0000; | |
+ | |
+ /DISCARD/ :{ | |
+ *(*.eh_frame); | |
+ } | |
+} | |
diff --git a/kernel/arch/arm64/mp.c b/kernel/arch/arm64/mp.c | |
new file mode 100644 | |
index 0000000..5a10f99 | |
--- /dev/null | |
+++ b/kernel/arch/arm64/mp.c | |
@@ -0,0 +1,21 @@ | |
+#include <task.h> | |
+ | |
+struct cpuvar cpuvar; | |
+ | |
+void halt(void) { | |
+ while (true) { | |
+ __asm__ __volatile__("wfi"); | |
+ } | |
+} | |
+ | |
+void panic_lock(void) { | |
+ // Do nothing: we don't support multiprocessors. | |
+} | |
+ | |
+void mp_start(void) { | |
+ // Do nothing: we don't support multiprocessors. | |
+} | |
+ | |
+void mp_reschedule(void) { | |
+ // Do nothing: we don't support multiprocessors. | |
+} | |
diff --git a/kernel/arch/arm64/peripherals.c b/kernel/arch/arm64/peripherals.c | |
new file mode 100644 | |
index 0000000..cc2647c | |
--- /dev/null | |
+++ b/kernel/arch/arm64/peripherals.c | |
@@ -0,0 +1,137 @@ | |
+#include <types.h> | |
+#include <printk.h> | |
+#include "peripherals.h" | |
+ | |
+ | |
+/* | |
+ * Copyright (C) 2018 bzt (bztsrc@github) | |
+ * | |
+ * Permission is hereby granted, free of charge, to any person | |
+ * obtaining a copy of this software and associated documentation | |
+ * files (the "Software"), to deal in the Software without | |
+ * restriction, including without limitation the rights to use, copy, | |
+ * modify, merge, publish, distribute, sublicense, and/or sell copies | |
+ * of the Software, and to permit persons to whom the Software is | |
+ * furnished to do so, subject to the following conditions: | |
+ * | |
+ * The above copyright notice and this permission notice shall be | |
+ * included in all copies or substantial portions of the Software. | |
+ * | |
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
+ * DEALINGS IN THE SOFTWARE. | |
+ * | |
+ */ | |
+ | |
+#define MMIO_BASE 0x3F000000 | |
+ | |
+#define GPFSEL0 ((volatile unsigned int*)(MMIO_BASE+0x00200000)) | |
+#define GPFSEL1 ((volatile unsigned int*)(MMIO_BASE+0x00200004)) | |
+#define GPFSEL2 ((volatile unsigned int*)(MMIO_BASE+0x00200008)) | |
+#define GPFSEL3 ((volatile unsigned int*)(MMIO_BASE+0x0020000C)) | |
+#define GPFSEL4 ((volatile unsigned int*)(MMIO_BASE+0x00200010)) | |
+#define GPFSEL5 ((volatile unsigned int*)(MMIO_BASE+0x00200014)) | |
+#define GPSET0 ((volatile unsigned int*)(MMIO_BASE+0x0020001C)) | |
+#define GPSET1 ((volatile unsigned int*)(MMIO_BASE+0x00200020)) | |
+#define GPCLR0 ((volatile unsigned int*)(MMIO_BASE+0x00200028)) | |
+#define GPLEV0 ((volatile unsigned int*)(MMIO_BASE+0x00200034)) | |
+#define GPLEV1 ((volatile unsigned int*)(MMIO_BASE+0x00200038)) | |
+#define GPEDS0 ((volatile unsigned int*)(MMIO_BASE+0x00200040)) | |
+#define GPEDS1 ((volatile unsigned int*)(MMIO_BASE+0x00200044)) | |
+#define GPHEN0 ((volatile unsigned int*)(MMIO_BASE+0x00200064)) | |
+#define GPHEN1 ((volatile unsigned int*)(MMIO_BASE+0x00200068)) | |
+#define GPPUD ((volatile unsigned int*)(MMIO_BASE+0x00200094)) | |
+#define GPPUDCLK0 ((volatile unsigned int*)(MMIO_BASE+0x00200098)) | |
+#define GPPUDCLK1 ((volatile unsigned int*)(MMIO_BASE+0x0020009C)) | |
+ | |
+/* Auxilary mini UART registers */ | |
+#define AUX_ENABLE ((volatile unsigned int*)(MMIO_BASE+0x00215004)) | |
+#define AUX_MU_IO ((volatile unsigned int*)(MMIO_BASE+0x00215040)) | |
+#define AUX_MU_IER ((volatile unsigned int*)(MMIO_BASE+0x00215044)) | |
+#define AUX_MU_IIR ((volatile unsigned int*)(MMIO_BASE+0x00215048)) | |
+#define AUX_MU_LCR ((volatile unsigned int*)(MMIO_BASE+0x0021504C)) | |
+#define AUX_MU_MCR ((volatile unsigned int*)(MMIO_BASE+0x00215050)) | |
+#define AUX_MU_LSR ((volatile unsigned int*)(MMIO_BASE+0x00215054)) | |
+#define AUX_MU_MSR ((volatile unsigned int*)(MMIO_BASE+0x00215058)) | |
+#define AUX_MU_SCRATCH ((volatile unsigned int*)(MMIO_BASE+0x0021505C)) | |
+#define AUX_MU_CNTL ((volatile unsigned int*)(MMIO_BASE+0x00215060)) | |
+#define AUX_MU_STAT ((volatile unsigned int*)(MMIO_BASE+0x00215064)) | |
+#define AUX_MU_BAUD ((volatile unsigned int*)(MMIO_BASE+0x00215068)) | |
+ | |
+/** | |
+ * Set baud rate and characteristics (115200 8N1) and map to GPIO | |
+ */ | |
+void uart_init() | |
+{ | |
+ register unsigned int r; | |
+ | |
+ /* initialize UART */ | |
+ *AUX_ENABLE |=1; // enable UART1, AUX mini uart | |
+ *AUX_MU_CNTL = 0; | |
+ *AUX_MU_LCR = 3; // 8 bits | |
+ *AUX_MU_MCR = 0; | |
+ *AUX_MU_IER = 0; | |
+ *AUX_MU_IIR = 0xc6; // disable interrupts | |
+ *AUX_MU_BAUD = 270; // 115200 baud | |
+ /* map UART1 to GPIO pins */ | |
+ r=*GPFSEL1; | |
+ r&=~((7<<12)|(7<<15)); // gpio14, gpio15 | |
+ r|=(2<<12)|(2<<15); // alt5 | |
+ *GPFSEL1 = r; | |
+ *GPPUD = 0; // enable pins 14 and 15 | |
+ r=150; while(r--) { __asm__ __volatile__("nop"); } | |
+ *GPPUDCLK0 = (1<<14)|(1<<15); | |
+ r=150; while(r--) { __asm__ __volatile__("nop"); } | |
+ *GPPUDCLK0 = 0; // flush GPIO setup | |
+ *AUX_MU_CNTL = 3; // enable Tx, Rx | |
+} | |
+ | |
+/** | |
+ * Send a character | |
+ */ | |
+void uart_send(unsigned int c) { | |
+ /* wait until we can send */ | |
+ do{__asm__ __volatile__("nop");}while(!(*AUX_MU_LSR&0x20)); | |
+ /* write the character to the buffer */ | |
+ *AUX_MU_IO=c; | |
+} | |
+ | |
+/** | |
+ * Receive a character | |
+ */ | |
+char uart_getc() { | |
+ char r; | |
+ /* wait until something is in the buffer */ | |
+ do{__asm__ __volatile__("nop");}while(!(*AUX_MU_LSR&0x01)); | |
+ /* read it and return */ | |
+ r=(char)(*AUX_MU_IO); | |
+ /* convert carrige return to newline */ | |
+ return r=='\r'?'\n':r; | |
+} | |
+ | |
+ | |
+ | |
+static inline uint32_t mmio_read(vaddr_t addr) { | |
+ return *((volatile uint32_t *) addr); | |
+} | |
+ | |
+static inline void mmio_write(vaddr_t addr, uint32_t value) { | |
+ *((volatile uint32_t *) addr) = value; | |
+} | |
+ | |
+void arch_printchar(char ch) { | |
+ uart_send(ch); | |
+} | |
+ | |
+char kdebug_readchar(void) { | |
+ return '\0'; | |
+} | |
+ | |
+void arm_peripherals_init(void) { | |
+ uart_init(); | |
+} | |
diff --git a/kernel/arch/arm64/peripherals.h b/kernel/arch/arm64/peripherals.h | |
new file mode 100644 | |
index 0000000..fcfa347 | |
--- /dev/null | |
+++ b/kernel/arch/arm64/peripherals.h | |
@@ -0,0 +1,6 @@ | |
+#ifndef __ARM_PERIPHERALS_H__ | |
+#define __ARM_PERIPHERALS_H__ | |
+ | |
+void arm_peripherals_init(void); | |
+ | |
+#endif | |
diff --git a/kernel/arch/arm64/switch.S b/kernel/arch/arm64/switch.S | |
new file mode 100644 | |
index 0000000..8ef7768 | |
--- /dev/null | |
+++ b/kernel/arch/arm64/switch.S | |
@@ -0,0 +1,10 @@ | |
+.text | |
+ | |
+// void arm_task_switch(vaddr_t *prev_sp, vaddr_t next_sp); | |
+.global arm_task_switch | |
+arm_task_switch: | |
+ | |
+ | |
+.global arm_start_task | |
+arm_start_task: | |
+// bl stack_set_canary | |
diff --git a/kernel/arch/arm64/task.c b/kernel/arch/arm64/task.c | |
new file mode 100644 | |
index 0000000..9bdcc3d | |
--- /dev/null | |
+++ b/kernel/arch/arm64/task.c | |
@@ -0,0 +1,55 @@ | |
+#include <syscall.h> | |
+#include <cstring.h> | |
+#include <main.h> | |
+#include <task.h> | |
+#include <memory.h> | |
+ | |
+#define STACK_SIZE 1024 | |
+ | |
+void arm_start_task(void); | |
+ | |
+// Prepare the initial stack for arm_task_switch(). | |
+static void init_stack(struct task *task, vaddr_t pc) { | |
+ uint32_t *sp = (uint32_t *) ((vaddr_t) task->arch.stack_bottom + STACK_SIZE); | |
+ // Fill the exception stack frame. After the first context switch, the CPU | |
+ // always runs the kernel code in the handler mode because of exceptions | |
+ // (e.g. timer interrupts and system calls). | |
+ *--sp = 1 << 24; // psr | |
+ *--sp = pc | 1; // pc | |
+ *--sp = 0; // lr | |
+ *--sp = 0; // r12 | |
+ *--sp = 0; // r3 | |
+ *--sp = 0; // r2 | |
+ *--sp = 0; // r1 | |
+ *--sp = 0; // r0 | |
+ *--sp = 0xfffffff9; // return from exception | |
+ | |
+ *--sp = (vaddr_t) arm_start_task; // Task starts here. | |
+ int num_zeroed_regs = 8; // r4-r11 | |
+ for (int i = 0; i < num_zeroed_regs; i++) { | |
+ *--sp = 0; | |
+ } | |
+ | |
+ task->arch.stack = (vaddr_t) sp; | |
+} | |
+ | |
+error_t arch_task_create(struct task *task, vaddr_t pc) { | |
+ void *stack = kmalloc(STACK_SIZE); | |
+ if (!stack) { | |
+ return ERR_NO_MEMORY; | |
+ } | |
+ | |
+ task->arch.stack_bottom = stack; | |
+ init_stack(task, pc); | |
+ return OK; | |
+} | |
+ | |
+void arch_task_destroy(struct task *task) { | |
+ kfree((void *) task->arch.stack_bottom); | |
+} | |
+ | |
+void arm_task_switch(vaddr_t *prev_sp, vaddr_t next_sp); | |
+ | |
+void arch_task_switch(struct task *prev, struct task *next) { | |
+ arm_task_switch(&prev->arch.stack, next->arch.stack); | |
+} | |
diff --git a/kernel/arch/arm64/vm.c b/kernel/arch/arm64/vm.c | |
new file mode 100644 | |
index 0000000..0bf321b | |
--- /dev/null | |
+++ b/kernel/arch/arm64/vm.c | |
@@ -0,0 +1,38 @@ | |
+#include <memory.h> | |
+#include <syscall.h> | |
+#include <cstring.h> | |
+ | |
+int __temp_page; // unused as we don't use virtual memory | |
+ | |
+error_t vm_create(struct vm *vm) { | |
+ // Do nothing: we don't support virtual memory. | |
+ return OK; | |
+} | |
+ | |
+void vm_destroy(struct vm *vm) { | |
+ // Do nothing: we don't support virtual memory. | |
+} | |
+ | |
+error_t vm_link(struct vm *vm, vaddr_t vaddr, paddr_t paddr, | |
+ pageattrs_t attrs) { | |
+ // Do nothing: we don't support virtual memory. | |
+ return OK; | |
+} | |
+ | |
+void vm_unlink(struct vm *vm, vaddr_t vaddr) { | |
+ // Do nothing: we don't support virtual memory. | |
+} | |
+ | |
+paddr_t vm_resolve(struct vm *vm, vaddr_t vaddr) { | |
+ return vaddr; | |
+} | |
+ | |
+void arch_memcpy_from_user(void *dst, userptr_t src, size_t len) { | |
+ memcpy(dst, (void *) src, len); | |
+} | |
+void arch_memcpy_to_user(userptr_t dst, const void *src, size_t len) { | |
+ memcpy((void *) dst, src, len); | |
+} | |
+void arch_strncpy_from_user(char *dst, userptr_t src, size_t max_len) { | |
+ strncpy(dst, (char *) src, max_len); | |
+} | |
diff --git a/libs/common/arch/arm64/arch_types.h b/libs/common/arch/arm64/arch_types.h | |
new file mode 100644 | |
index 0000000..3320075 | |
--- /dev/null | |
+++ b/libs/common/arch/arm64/arch_types.h | |
@@ -0,0 +1,25 @@ | |
+#ifndef __ARCH_TYPES_H__ | |
+#define __ARCH_TYPES_H__ | |
+ | |
+typedef uint32_t pageattrs_t; | |
+typedef uint64_t size_t; | |
+typedef int64_t intmax_t; | |
+typedef uint64_t uintmax_t; | |
+typedef uint64_t paddr_t; | |
+typedef uint64_t vaddr_t; | |
+typedef uint64_t uintptr_t; | |
+ | |
+#define PAGE_SIZE 4096 | |
+#define PAGE_PRESENT (1 << 0) | |
+#define PAGE_WRITABLE (1 << 1) | |
+#define PAGE_USER (1 << 2) | |
+ | |
+typedef uint32_t pagefault_t; | |
+#define PF_PRESENT (1 << 0) | |
+#define PF_WRITE (1 << 1) | |
+#define PF_USER (1 << 2) | |
+ | |
+typedef struct { | |
+} trap_frame_t; | |
+ | |
+#endif | |
diff --git a/libs/common/arch/arm64/build.mk b/libs/common/arch/arm64/build.mk | |
new file mode 100644 | |
index 0000000..e69de29 | |
diff --git a/libs/resea/arch/arm64/arch/io.h b/libs/resea/arch/arm64/arch/io.h | |
new file mode 100644 | |
index 0000000..8bf41a8 | |
--- /dev/null | |
+++ b/libs/resea/arch/arm64/arch/io.h | |
@@ -0,0 +1,6 @@ | |
+#ifndef __RESEA_ARCH_IO_H__ | |
+#define __RESEA_ARCH_IO_H__ | |
+ | |
+// TODO: | |
+ | |
+#endif | |
diff --git a/libs/resea/arch/arm64/arch/syscall.h b/libs/resea/arch/arm64/arch/syscall.h | |
new file mode 100644 | |
index 0000000..3b9733d | |
--- /dev/null | |
+++ b/libs/resea/arch/arm64/arch/syscall.h | |
@@ -0,0 +1,26 @@ | |
+#ifndef __ARCH_SYSCALL_H__ | |
+#define __ARCH_SYSCALL_H__ | |
+ | |
+#include <types.h> | |
+ | |
+static inline long syscall(int n, long a1, long a2, long a3, long a4, long a5) { | |
+ register long r0 __asm__("r0") = n; | |
+ register long r1 __asm__("r1") = a1; | |
+ register long r2 __asm__("r2") = a2; | |
+ register long r3 __asm__("r3") = a3; | |
+ register long r4 __asm__("r4") = a4; | |
+ register long r5 __asm__("r5") = a5; | |
+ register long r6 __asm__("r6") = r6; | |
+ | |
+ /* FIXME: | |
+ __asm__ __volatile__( | |
+ "svc 0" | |
+ : "=r"(r0), "=r"(r6) | |
+ : "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5) | |
+ : "ip", "memory"); | |
+ */ | |
+ | |
+ return r6; // FIXME: | |
+} | |
+ | |
+#endif | |
diff --git a/libs/resea/arch/arm64/build.mk b/libs/resea/arch/arm64/build.mk | |
new file mode 100644 | |
index 0000000..f9151d2 | |
--- /dev/null | |
+++ b/libs/resea/arch/arm64/build.mk | |
@@ -0,0 +1 @@ | |
+obj-y += start.o | |
diff --git a/libs/resea/arch/arm64/start.S b/libs/resea/arch/arm64/start.S | |
new file mode 100644 | |
index 0000000..b112ce0 | |
--- /dev/null | |
+++ b/libs/resea/arch/arm64/start.S | |
@@ -0,0 +1,17 @@ | |
+.text | |
+.global _start | |
+_start: | |
+// TODO: set sp | |
+ | |
+ // Initialize the user library. | |
+// bl resea_init | |
+ | |
+ // Call main(). | |
+// bl main | |
+ | |
+ // main() has returned. Exit the current task. | |
+// bl task_exit | |
+ | |
+.global halt | |
+halt: | |
+ b halt | |
diff --git a/libs/resea/arch/arm64/user.ld b/libs/resea/arch/arm64/user.ld | |
new file mode 100644 | |
index 0000000..099698e | |
--- /dev/null | |
+++ b/libs/resea/arch/arm64/user.ld | |
@@ -0,0 +1,58 @@ | |
+PHDRS { | |
+ text PT_LOAD; | |
+ data PT_LOAD; | |
+ bss PT_LOAD; | |
+} | |
+ | |
+SECTIONS { | |
+ /* XXX: For simplicity of the implementation, kernel's ELF loader assumes | |
+ the address and the length of program headers are aligned to 4096 | |
+ (PAGE_SIZE). */ | |
+ . = 0x100000; | |
+ | |
+ .text :{ | |
+ *(.text*) | |
+ } :text | |
+ | |
+ .rodata :{ | |
+ *(.rodata*) | |
+ . = ALIGN(4096); // See the XXX comment above. | |
+ } :text | |
+ | |
+ .data :{ | |
+ *(.data*) | |
+ . = ALIGN(4096); // See the XXX comment above. | |
+ } :data | |
+ | |
+ __zeroed_pages = .; | |
+ | |
+ .bss :{ | |
+ __bss = .; | |
+ *(.bss*); | |
+ __bss_end = .; | |
+ | |
+ . = ALIGN(4); | |
+ __heap = .; | |
+ . += 4096; | |
+ . = ALIGN(4096); // See the XXX comment above. | |
+ __heap_end = .; | |
+ } :bss | |
+ | |
+ . = ALIGN(16); | |
+ __stack = .; | |
+ . += 0x4000; | |
+ __stack_end = .; | |
+ | |
+ . = ALIGN(16); | |
+ __heap = .; | |
+ . = 0x05000000; | |
+ __heap_end = .; | |
+ | |
+ __free_vaddr = .; | |
+ . = 0x0a000000; | |
+ __free_vaddr_end = .; | |
+ | |
+ /DISCARD/ :{ | |
+ *(.ARM.exidx) | |
+ } | |
+} | |
diff --git a/servers/bootstrap/bootfs.S b/servers/bootstrap/bootfs.S | |
index 355867d..de424a1 100644 | |
--- a/servers/bootstrap/bootfs.S | |
+++ b/servers/bootstrap/bootfs.S | |
@@ -1,5 +1,13 @@ | |
+#include <config.h> | |
+ | |
.rodata | |
+#ifdef CONFIG_ARCH_ARM64 | |
+// FIXME: I dunno why but in arm64, .align directive takes a exponent. | |
+.align 12 | |
+#else | |
.align 4096 | |
+#endif | |
+ | |
.global __bootfs, __bootfs_end | |
__bootfs: | |
.incbin BOOTFS_PATH |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment