diff --git a/.vscode/launch.json b/.vscode/launch.json index d5bc70194..5b01958f4 100755 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -46,7 +46,7 @@ "environment": [], "externalConsole": false, // "miDebuggerPath": "/opt/homebrew/bin/arm-none-eabi-gdb", - "miDebuggerPath": "/Users/zhangzheng/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-gdb", + "miDebuggerPath": "/home/zhangzheng/gcc-arm-10.3-2021.07-aarch64-aarch64-none-elf/bin/aarch64-none-elf-gdb", // "miDebuggerPath": "/home/zhangzheng/gcc-arm-none-eabi-5_4-2016q3/bin/arm-none-eabi-gdb", "miDebuggerServerAddress": "127.0.0.1:3333", "MIMode": "gdb", diff --git a/.vscode/settings.json b/.vscode/settings.json index 1ff72f840..646881889 100755 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -329,7 +329,21 @@ "gui_interface_extern.h": "c", "gui.h": "c", "gui_timeout.h": "c", - "bitmap.h": "c" + "bitmap.h": "c", + "early_boot.h": "c", + "sysregs.h": "c", + "types_asm.h": "c", + "pager.h": "c", + "thread_arch.h": "c", + "aarch64_ptregs.h": "c", + "psci.h": "c", + "buddy.h": "c", + "atomics.h": "c", + "asm_config.h": "c", + "slab.h": "c", + "arm_local_reg.h": "c", + "timer.h": "c", + "arm_gicv2.h": "c" }, "cortex-debug.showRTOS": false, "cortex-debug.variableUseNaturalFormat": false, diff --git a/CMakeLists.txt b/CMakeLists.txt index bcb492abe..10fec5300 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,15 +26,13 @@ execute_process( ) string(STRIP ${DATE} DATE) string(STRIP ${TIME} TIME) -# string(STRIP ${COMMIT} COMMIT) -# string(STRIP ${BRANCH} BRANCH) set(code_version ${BRANCH}-${COMMIT} CACHE STRING " " FORCE) set(compile_time "${DATE}\" \"${TIME}" CACHE STRING " " FORCE) add_subdirectory(mkrtos_bootstrap) add_subdirectory(mkrtos_knl) -add_subdirectory(mkrtos_img) -add_subdirectory(mkrtos_user) +# add_subdirectory(mkrtos_img) +# add_subdirectory(mkrtos_user) diff --git a/aarch64.cmake b/aarch64.cmake new file mode 100644 index 000000000..a01f8aa41 --- /dev/null +++ b/aarch64.cmake @@ -0,0 +1,22 @@ + +message("========use aarch64.cmake") + +set(CMAKE_C_FLAGS "-O0 -g3 -D=MKRTOS \ +-std=gnu11 -ffunction-sections -fdata-sections -fno-builtin -u=_printf_float \ +-nostartfiles -nodefaultlibs -nostdlib -nostdinc -Xlinker \ +-fno-stack-protector -Wl,--gc-sections \ +-include ${CMAKE_SOURCE_DIR}/build/autoconf.h \ +" CACHE STRING "" FORCE) + +set(CMAKE_CXX_FLAGS "-O0 -g3 -D=MKRTOS -std=c++11 \ +-fmessage-length=0 -Xlinker --print-map -Wall -W -fno-stack-protector -g \ + -u=_printf_float \ +-ffunction-sections -fdata-sections -fno-builtin -nostartfiles -nodefaultlibs -nostdlib -nostdinc -Xlinker \ +-include ${CMAKE_SOURCE_DIR}/build/autoconf.h \ +" CACHE STRING "" FORCE) + +set(CMAKE_ASM_FLAGS "-O0 -g3 -D=MKRTOS \ +-u=_printf_float -std=gnu11 -ffunction-sections -fdata-sections -fno-builtin \ +-nostartfiles -nodefaultlibs -nostdlib -nostdinc -Xlinker -fno-stack-protector \ +-include ${CMAKE_SOURCE_DIR}/build/autoconf.h \ +" CACHE STRING "" FORCE) \ No newline at end of file diff --git a/armv7_8.cmake b/armv7_8.cmake new file mode 100644 index 000000000..14ff2d53c --- /dev/null +++ b/armv7_8.cmake @@ -0,0 +1,21 @@ +message("========use armv7_8.cmake") + +set(CMAKE_C_FLAGS "-mcpu=${CONFIG_ARCH} -O0 -g3 -mfloat-abi=${CONFIG_FLOAT_TYPE} -mthumb -mno-thumb-interwork -D=MKRTOS \ +-std=gnu11 -ffunction-sections -fdata-sections -fno-builtin -u=_printf_float \ +-nostartfiles -nodefaultlibs -nostdlib -nostdinc -Xlinker \ +-fno-stack-protector -Wl,--gc-sections \ +-include ${CMAKE_SOURCE_DIR}/build/autoconf.h \ +" CACHE STRING "" FORCE) + +set(CMAKE_CXX_FLAGS "-mcpu=${CONFIG_ARCH} -O0 -g3 -mfloat-abi=${CONFIG_FLOAT_TYPE} -mthumb -mno-thumb-interwork -D=MKRTOS -std=c++11 \ +-fmessage-length=0 -Xlinker --print-map -Wall -W -fno-stack-protector -g \ + -u=_printf_float \ +-ffunction-sections -fdata-sections -fno-builtin -nostartfiles -nodefaultlibs -nostdlib -nostdinc -Xlinker \ +-include ${CMAKE_SOURCE_DIR}/build/autoconf.h \ +" CACHE STRING "" FORCE) + +set(CMAKE_ASM_FLAGS "-mcpu=${CONFIG_ARCH} -O0 -g3 -mfloat-abi=${CONFIG_FLOAT_TYPE} -mthumb -mno-thumb-interwork -D=MKRTOS \ +-u=_printf_float -std=gnu11 -ffunction-sections -fdata-sections -fno-builtin \ +-nostartfiles -nodefaultlibs -nostdlib -nostdinc -Xlinker -fno-stack-protector \ +-include ${CMAKE_SOURCE_DIR}/build/autoconf.h \ +" CACHE STRING "" FORCE) \ No newline at end of file diff --git a/mkrtos_bootstrap/CMakeLists.txt b/mkrtos_bootstrap/CMakeLists.txt index 5ecdc2804..fa1f2e2fa 100755 --- a/mkrtos_bootstrap/CMakeLists.txt +++ b/mkrtos_bootstrap/CMakeLists.txt @@ -85,15 +85,42 @@ elseif(${CONFIG_CPU_TYPE} STREQUAL "swm34s" ) ${CMAKE_SOURCE_DIR}/mkrtos_bsp/SWM34/SWM341_StdPeriph_Driver/SWM341_StdPeriph_Driver ) add_subdirectory(bsp/SWM34S) +elseif(${CONFIG_CPU_TYPE} STREQUAL "aarch64_qemu" ) + include_directories( + ${CMAKE_SOURCE_DIR}/mkrtos_bootstrap/bsp/AARCH64_QEMU + ) + add_subdirectory(bsp/AARCH64_QEMU) endif() +add_custom_target( + gen_sys_cpio + + COMMAND + cd ${CMAKE_SOURCE_DIR}/build/output/cpio + COMMAND + ls | cpio -H newc -o > ${CMAKE_SOURCE_DIR}/build/output/rootfs.cpio + COMMAND + cd ${CMAKE_SOURCE_DIR}/build/output + COMMAND + ${CMAKE_OBJCOPY} -I binary -O elf64-littleaarch64 -B aarch64 rootfs.cpio rootfs.cpio.elf --rename-section .data=.cpio + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/build/output + BYPRODUCTS ${CMAKE_SOURCE_DIR}/build/output/rootfs.cpio.elf +) +add_dependencies( + gen_sys_cpio + mkrtos_dump +) + +set_source_files_properties(${CMAKE_SOURCE_DIR}/build/output/rootfs.cpio.elf PROPERTIES EXTERNAL_OBJECT true) + add_executable(bootstrap.elf ${deps} + ${CMAKE_SOURCE_DIR}/build/output/rootfs.cpio.elf ) -message("CONFIG_CPU_TYPE"=${CONFIG_CPU_TYPE}) +# message("CONFIG_CPU_TYPE="${CONFIG_CPU_TYPE}) string(TOUPPER ${CONFIG_CPU_TYPE} cpu_type) set_target_properties(bootstrap.elf PROPERTIES LINK_FLAGS -"-T ${CMAKE_CURRENT_LIST_DIR}/bsp/${cpu_type}/link.lds --gc-section ") +"-T ${CMAKE_CURRENT_LIST_DIR}/bsp/${cpu_type}/link.lds") target_link_libraries( bootstrap.elf @@ -110,13 +137,14 @@ add_custom_target( COMMAND mkdir -p ${CMAKE_SOURCE_DIR}/build/output COMMAND - cp bootstrap.bin ${CMAKE_SOURCE_DIR}/build/output/bootstrap + mkdir -p ${CMAKE_SOURCE_DIR}/build/output/cpio COMMAND - cp bootstrap.bin ${CMAKE_SOURCE_DIR}/build/output/bootstrap.bin + cp bootstrap.bin ${CMAKE_SOURCE_DIR}/build/output/bootstrap COMMAND cp bootstrap.elf ${CMAKE_SOURCE_DIR}/build/output/bootstrap.elf COMMAND ${CMAKE_SIZE} bootstrap.elf ) add_dependencies(bootstrap_dump bootstrap.elf) -add_dependencies(bootstrap.elf boot_bsp) \ No newline at end of file +add_dependencies(bootstrap.elf boot_bsp) +add_dependencies(bootstrap.elf gen_sys_cpio) \ No newline at end of file diff --git a/mkrtos_bootstrap/bsp/AARCH64_QEMU/CMakeLists.txt b/mkrtos_bootstrap/bsp/AARCH64_QEMU/CMakeLists.txt new file mode 100755 index 000000000..114221744 --- /dev/null +++ b/mkrtos_bootstrap/bsp/AARCH64_QEMU/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.13) + + +file(GLOB_RECURSE deps *.S *.s *.C *.c) + +add_library(boot_bsp STATIC ${deps}) +target_include_directories( + boot_bsp + PUBLIC +) + +target_link_libraries(boot_bsp + PRIVATE +) diff --git a/mkrtos_bootstrap/bsp/AARCH64_QEMU/aarch64_start.c b/mkrtos_bootstrap/bsp/AARCH64_QEMU/aarch64_start.c new file mode 100644 index 000000000..49392b85e --- /dev/null +++ b/mkrtos_bootstrap/bsp/AARCH64_QEMU/aarch64_start.c @@ -0,0 +1,38 @@ + +#include +#include +#include +#include "cpio.h" +__ALIGN__(16) +uint64_t stack[4096 / sizeof(uint64_t)]; + + +#define KERNEL_NAME "mkrtos.elf" + +// 内核的启动地址,其它核跳转使用 +extern uint64_t knl_entry; +// #define KERNEL_NAME "mkrtos_smart.elf" +#define KERNEL_IMG_START_ADDR (0x40000000 + 0x01000000 + 0x4000) + +typedef void (*main_func)(umword_t cpio_addr); + +void jump2kernel(addr_t cpio_start, addr_t cpio_end) +{ + uart_init(); + uart_write_str("bootstrap...\n"); + umword_t knl_st_addr = cpio_find_file((umword_t)cpio_start, (umword_t)cpio_end, KERNEL_NAME); + if (!knl_st_addr) + { + while (1) + ; + } + Elf64_Addr entry; + + elf_load_knl(knl_st_addr, &entry); + main_func entry_fun = (main_func)entry; + knl_entry = entry; + entry_fun((mword_t)cpio_start); + + while (1) + ; +} diff --git a/mkrtos_bootstrap/bsp/AARCH64_QEMU/cpio.c b/mkrtos_bootstrap/bsp/AARCH64_QEMU/cpio.c new file mode 100644 index 000000000..617a58fd0 --- /dev/null +++ b/mkrtos_bootstrap/bsp/AARCH64_QEMU/cpio.c @@ -0,0 +1,82 @@ +#include "mk_sys.h" +#include "cpio.h" +#include +#define MIN(a, b) ((a) < (b) ? (a) : (b)) //!< 最小值 +#define ALIGN(mem, align) (((mem) + ((align) - 1)) & (~((align) - 1))) //!< 向上对齐 + +umword_t cpio_find_file(umword_t st, umword_t en, const char *name) +{ + uint8_t rByte; + int32_t bk_inx; + cpio_fs_t *file_info; + + for (umword_t i = st; st < en;) + { + file_info = (cpio_fs_t *)i; + + if (check_magic((char *)file_info) < 0) + { + return 0; + } + int name_size = htoi(file_info->c_namesize, 8); + const char *f_name = (char *)(i + sizeof(cpio_fs_t)); + if (strcmp(f_name, name) == 0) + { + return (mword_t)(ALIGN(i + sizeof(cpio_fs_t) + name_size, 4)); + } + + if (strcmp("TRAILER!!", f_name) == 0) + { + return 0; + } + int file_size = htoi(file_info->c_filesize, 8); + + i = ALIGN(ALIGN(i + sizeof(cpio_fs_t) + name_size, 4) + + file_size, + 4); + } + return 0; +} + +int htoi(char *str, int len) +{ + int n = 0; + int i = 0; + + if (str == NULL || len <= 0) + return -1; + for (i = 0; i < len; i++) + { + if (str[i] != '0') + { + break; + } + } + str += i; + while (1) + { + if (*str >= '0' && *str <= '9') + { + n = 16 * n + (*str - '0'); + } + else if (*str >= 'A' && *str <= 'F') // 十六进制还要判断字符是不是在A-F或者a-f之间 + { + n = 16 * n + (*str - 'A' + 10); + } + else if (*str >= 'a' && *str <= 'f') + { + n = 16 * n + (*str - 'a' + 10); + } + else + { + break; + } + str++; + i++; + if (i >= len) + { + break; + } + } + return n; +} diff --git a/mkrtos_bootstrap/bsp/AARCH64_QEMU/cpio.h b/mkrtos_bootstrap/bsp/AARCH64_QEMU/cpio.h new file mode 100644 index 000000000..493723a3c --- /dev/null +++ b/mkrtos_bootstrap/bsp/AARCH64_QEMU/cpio.h @@ -0,0 +1,34 @@ +#pragma once +#include "mk_sys.h" +//! 26bytes +#pragma pack(1) +typedef struct cpio_fs +{ + char c_magic[6]; + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[8]; + char c_filesize[8]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_check[8]; +} cpio_fs_t; + +static inline int64_t check_magic(char *magic) +{ + if (magic[0] == '0' && magic[1] == '7' && magic[2] == '0' && + magic[3] == '7' && magic[4] == '0' && magic[5] == '1') + { + return 0; + } + return -1; +} + +int htoi(char *str, int len); +umword_t cpio_find_file(umword_t st, umword_t en, const char *name); diff --git a/mkrtos_bootstrap/bsp/AARCH64_QEMU/elf.h b/mkrtos_bootstrap/bsp/AARCH64_QEMU/elf.h new file mode 100644 index 000000000..bdad3b069 --- /dev/null +++ b/mkrtos_bootstrap/bsp/AARCH64_QEMU/elf.h @@ -0,0 +1,60 @@ +#pragma once + +#include +typedef uint16_t Elf64_Half; +typedef uint32_t Elf64_Word; +typedef uint64_t Elf64_Addr; +typedef uint64_t Elf64_Off; +typedef uint64_t Elf64_Xword; +#define EI_NIDENT (16) + +#pragma pack(1) +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; /* 一个字节数组用来确认文件是否是一个ELF文件 */ + Elf64_Half e_type; /* 描述文件是,可执行文件elf=2,重定位so=3 */ + Elf64_Half e_machine; /* 目标主机架构 */ + Elf64_Word e_version; /* ELF文件格式的版本 */ + Elf64_Addr e_entry; /* 入口点虚拟地址 */ + Elf64_Off e_phoff; /* 程序头文件偏移 */ + Elf64_Off e_shoff; /* 节头表文件偏移 */ + Elf64_Word e_flags; /* ELF文件标志 */ + Elf64_Half e_ehsize; /* ELF头大小 */ + Elf64_Half e_phentsize; /* 程序头大小 */ + Elf64_Half e_phnum; /* 程序头表计数 */ + Elf64_Half e_shentsize; /* 节头表大小 */ + Elf64_Half e_shnum; /* 节头表计数 */ + Elf64_Half e_shstrndx; /* 字符串表索引节头 */ +} Elf64_Ehdr; +#pragma pack(1) +typedef struct +{ + Elf64_Word p_type; /* Segment type */ + Elf64_Word p_flags; /* Segment flags */ + Elf64_Off p_offset; /* Segment file offset */ + Elf64_Addr p_vaddr; /* Segment virtual address */ + Elf64_Addr p_paddr; /* Segment physical address */ + Elf64_Xword p_filesz; /* Segment size in file */ + Elf64_Xword p_memsz; /* Segment size in memory */ + Elf64_Xword p_align; /* Segment alignment */ +} Elf64_Phdr; +#define PT_NULL 0 /* Program header table entry unused */ +#define PT_LOAD 1 /* Loadable program segment */ +#define PT_DYNAMIC 2 /* Dynamic linking information */ +#define PT_INTERP 3 /* Program interpreter */ +#define PT_NOTE 4 /* Auxiliary information */ +#define PT_SHLIB 5 /* Reserved */ +#define PT_PHDR 6 /* Entry for header table itself */ +#define PT_TLS 7 /* Thread-local storage segment */ +#define PT_NUM 8 /* Number of defined types */ +#define PT_LOOS 0x60000000 /* Start of OS-specific */ +#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */ +#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */ +#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ +#define PT_LOSUNW 0x6ffffffa +#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ +#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */ +#define PT_HISUNW 0x6fffffff +#define PT_HIOS 0x6fffffff /* End of OS-specific */ +#define PT_LOPROC 0x70000000 /* Start of processor-specific */ +#define PT_HIPROC 0x7fffffff /* End of processor-specific */ \ No newline at end of file diff --git a/mkrtos_bootstrap/bsp/AARCH64_QEMU/elf_loader.c b/mkrtos_bootstrap/bsp/AARCH64_QEMU/elf_loader.c new file mode 100644 index 000000000..7745569cb --- /dev/null +++ b/mkrtos_bootstrap/bsp/AARCH64_QEMU/elf_loader.c @@ -0,0 +1,21 @@ + +#include +#include + +void elf_load_knl(mword_t elf_data, Elf64_Addr *entry) +{ + Elf64_Ehdr *elf_header; + + elf_header = (Elf64_Ehdr *)elf_data; + *entry = elf_header->e_entry; + int size = elf_header->e_phentsize; + Elf64_Phdr *elf_phdr = (Elf64_Phdr *)(elf_header->e_phoff + elf_data); + + for (int i = 0; i < elf_header->e_phnum; i++, elf_phdr++) + { + if (elf_phdr->p_type == PT_LOAD) + { + memcpy((char *)elf_phdr->p_paddr, (char *)(elf_data + elf_phdr->p_offset), elf_phdr->p_filesz); + } + } +} diff --git a/mkrtos_bootstrap/bsp/AARCH64_QEMU/elf_loader.h b/mkrtos_bootstrap/bsp/AARCH64_QEMU/elf_loader.h new file mode 100644 index 000000000..984eed26b --- /dev/null +++ b/mkrtos_bootstrap/bsp/AARCH64_QEMU/elf_loader.h @@ -0,0 +1,5 @@ +#pragma once +#include +#include + +void elf_load_knl(mword_t elf_data, Elf64_Addr *entry); diff --git a/mkrtos_bootstrap/bsp/AARCH64_QEMU/link.lds b/mkrtos_bootstrap/bsp/AARCH64_QEMU/link.lds new file mode 100755 index 000000000..99e150eba --- /dev/null +++ b/mkrtos_bootstrap/bsp/AARCH64_QEMU/link.lds @@ -0,0 +1,70 @@ +ENTRY(_start); + +SECTIONS +{ + /* + * 0x40000000 + * + * 这里“.”表示location counter,当前位置 + */ + . = 0x40000000 + 0x01000000; + /* + * text代码段 + */ + _text = .; + .text : + { + *(.text) + } + _etext = .; + + /* + * 只读数据段 + */ + + _rodata = .; + .rodata : + { + *(.rodata) + } + _erodata = .; + + + /* + * 数据段 + */ + _data = .; + .data : + { + *(.data) + + . = ALIGN(0x8); + _pre_cpu_data_start = .; + KEEP (*(.data.per_cpu)) + _pre_cpu_data_end = .; + } + _edata = .; + + /* + * bss段 + * + * ALIGN(8)表示8个字节对齐 + * bss_begin的起始地址以8字节对齐 + */ + . = ALIGN(0x8); + _bss = .; + bss_begin = .; + .bss : + { + *(.bss*) + } + bss_end = .; + _ebss = .; + + . = ALIGN(0x8); + .cpio : { + cpio_start = .; + *(.cpio*) + cpio_end = .; + } +} diff --git a/mkrtos_bootstrap/bsp/AARCH64_QEMU/mk_sys.h b/mkrtos_bootstrap/bsp/AARCH64_QEMU/mk_sys.h new file mode 100644 index 000000000..878138a4d --- /dev/null +++ b/mkrtos_bootstrap/bsp/AARCH64_QEMU/mk_sys.h @@ -0,0 +1,62 @@ +#pragma once + +typedef signed char int8_t; +typedef signed short int16_t; +typedef signed int int32_t; + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; + +typedef unsigned long long uint64_t; +typedef long long int64_t; + +typedef unsigned long umword_t; +typedef unsigned short uhmword_t; +typedef long mword_t; + +typedef signed long int intptr_t; +typedef unsigned long int uintptr_t; + +typedef umword_t size_t; +typedef mword_t ssize_t; +typedef umword_t ptr_t; +typedef char bool_t; +typedef unsigned long obj_addr_t; +typedef umword_t uintptr_t; +typedef umword_t addr_t; +typedef umword_t obj_handler_t; +typedef umword_t time_t; +typedef umword_t pid_t; +#ifndef NULL +#define NULL ((void *)0) +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE (!(FALSE)) +#endif + +#define WORD_BYTES (sizeof(void *)) +#define WORD_BITS (sizeof(void *) * 8) + +#define __ALIGN__(size) __attribute__((aligned(size))) + +#define read_reg(addr) (*((volatile umword_t *)(addr))) +#define write_reg(addr, data) \ + do \ + { \ + (*((volatile umword_t *)(addr))) = data; \ + } while (0) + +#define read_reg32(addr) (*((volatile uint32_t *)(addr))) +#define write_reg32(addr, data) \ + do \ + { \ + (*((volatile uint32_t *)(addr))) = (uint32_t)data; \ + } while (0) + +void jump2kernel(addr_t cpio_start, addr_t cpio_end); diff --git a/mkrtos_bootstrap/bsp/AARCH64_QEMU/start.S b/mkrtos_bootstrap/bsp/AARCH64_QEMU/start.S new file mode 100644 index 000000000..43324e933 --- /dev/null +++ b/mkrtos_bootstrap/bsp/AARCH64_QEMU/start.S @@ -0,0 +1,37 @@ + +/* 8字节对齐,否则会出错*/ +.align 3 +.globl sp_addr +.section ".data.boot" +sp_addr: + .quad stack + 4096 - 8 //pt regs is 320 bytes. + +.align 3 +.globl knl_entry +.section ".data.boot" +knl_entry: + .quad 0 + +.section ".text.boot" +.globl _start +_start: + msr daifset, #0xf // 关闭中断 + //进入多核启动流程 + mrs x0, mpidr_el1 // 读取该寄存器获取处理器id + and x0, x0,#0xFF // Check processor id + cbz x0, master // Hang for all non-primary CPU + //spin table + ldr x1, = knl_entry +spin_jump: + ldr x3, [x1, #0] + cbz x3, spin_jump + br x3 + b . + +master: + ldr x8, = sp_addr + ldr x9, [x8] + mov sp, x9 + bl main + + b . \ No newline at end of file diff --git a/mkrtos_bootstrap/bsp/AARCH64_QEMU/uart.c b/mkrtos_bootstrap/bsp/AARCH64_QEMU/uart.c new file mode 100644 index 000000000..4250ae3af --- /dev/null +++ b/mkrtos_bootstrap/bsp/AARCH64_QEMU/uart.c @@ -0,0 +1,160 @@ +#include "mk_sys.h" + +#define UART01x_DR 0x00 /* Data read or written from the interface. */ +#define UART01x_RSR 0x04 /* Receive status register (Read). */ +#define UART01x_ECR 0x04 /* Error clear register (Write). */ +#define UART010_LCRH 0x08 /* Line control register, high byte. */ +#define ST_UART011_DMAWM 0x08 /* DMA watermark configure register. */ +#define UART010_LCRM 0x0C /* Line control register, middle byte. */ +#define ST_UART011_TIMEOUT 0x0C /* Timeout period register. */ +#define UART010_LCRL 0x10 /* Line control register, low byte. */ +#define UART010_CR 0x14 /* Control register. */ +#define UART01x_FR 0x18 /* Flag register (Read only). */ +#define UART010_IIR 0x1C /* Interrupt identification register (Read). */ +#define UART010_ICR 0x1C /* Interrupt clear register (Write). */ +#define ST_UART011_LCRH_RX 0x1C /* Rx line control register. */ +#define UART01x_ILPR 0x20 /* IrDA low power counter register. */ +#define UART011_IBRD 0x24 /* Integer baud rate divisor register. */ +#define UART011_FBRD 0x28 /* Fractional baud rate divisor register. */ +#define UART011_LCRH 0x2c /* Line control register. */ +#define UART011_LCRH_WLEN_8 0x60 +#define ST_UART011_LCRH_TX 0x2c /* Tx Line control register. */ +#define UART011_CR 0x30 /* Control register. */ +#define UART011_IFLS 0x34 /* Interrupt fifo level select. */ +#define UART011_IMSC 0x38 /* Interrupt mask. */ +#define UART011_RIS 0x3c /* Raw interrupt status. */ +#define UART011_MIS 0x40 /* Masked interrupt status. */ +#define UART011_ICR 0x44 /* Interrupt clear register. */ +#define UART011_DMACR 0x48 /* DMA control register. */ +#define ST_UART011_XFCR 0x50 /* XON/XOFF control register. */ +#define ST_UART011_XON1 0x54 /* XON1 register. */ +#define ST_UART011_XON2 0x58 /* XON2 register. */ +#define ST_UART011_XOFF1 0x5C /* XON1 register. */ +#define ST_UART011_XOFF2 0x60 /* XON2 register. */ +#define ST_UART011_ITCR 0x80 /* Integration test control register. */ +#define ST_UART011_ITIP 0x84 /* Integration test input register. */ +#define ST_UART011_ABCR 0x100 /* Autobaud control register. */ +#define ST_UART011_ABIMSC 0x15C /* Autobaud interrupt mask/clear register. */ + +#define UART011_FR_RI 0x100 +#define UART011_FR_TXFE 0x080 +#define UART011_FR_RXFF 0x040 +#define UART01x_FR_TXFF 0x020 +#define UART01x_FR_RXFE 0x010 +#define UART01x_FR_BUSY 0x008 +#define UART01x_FR_DCD 0x004 +#define UART01x_FR_DSR 0x002 +#define UART01x_FR_CTS 0x001 +#define UART01x_FR_TMSK (UART01x_FR_TXFF + UART01x_FR_BUSY) + +#define UART011_CR_CTSEN 0x8000 /* CTS hardware flow control */ +#define UART011_CR_RTSEN 0x4000 /* RTS hardware flow control */ +#define UART011_CR_OUT2 0x2000 /* OUT2 */ +#define UART011_CR_OUT1 0x1000 /* OUT1 */ +#define UART011_CR_RTS 0x0800 /* RTS */ +#define UART011_CR_DTR 0x0400 /* DTR */ +#define UART011_CR_RXE 0x0200 /* receive enable */ +#define UART011_CR_TXE 0x0100 /* transmit enable */ +#define UART011_CR_LBE 0x0080 /* loopback enable */ +#define UART010_CR_RTIE 0x0040 +#define UART010_CR_TIE 0x0020 +#define UART010_CR_RIE 0x0010 +#define UART010_CR_MSIE 0x0008 +#define ST_UART011_CR_OVSFACT 0x0008 /* Oversampling factor */ +#define UART01x_CR_IIRLP 0x0004 /* SIR low power mode */ +#define UART01x_CR_SIREN 0x0002 /* SIR enable */ +#define UART01x_CR_UARTEN 0x0001 /* UART enable */ + +#define UART011_OEIM (1 << 10) /* overrun error interrupt mask */ +#define UART011_BEIM (1 << 9) /* break error interrupt mask */ +#define UART011_PEIM (1 << 8) /* parity error interrupt mask */ +#define UART011_FEIM (1 << 7) /* framing error interrupt mask */ +#define UART011_RTIM (1 << 6) /* receive timeout interrupt mask */ +#define UART011_TXIM (1 << 5) /* transmit interrupt mask */ +#define UART011_RXIM (1 << 4) /* receive interrupt mask */ +#define UART011_DSRMIM (1 << 3) /* DSR interrupt mask */ +#define UART011_DCDMIM (1 << 2) /* DCD interrupt mask */ +#define UART011_CTSMIM (1 << 1) /* CTS interrupt mask */ +#define UART011_RIMIM (1 << 0) /* RI interrupt mask */ + +#define UART011_OEIS (1 << 10) /* overrun error interrupt status */ +#define UART011_BEIS (1 << 9) /* break error interrupt status */ +#define UART011_PEIS (1 << 8) /* parity error interrupt status */ +#define UART011_FEIS (1 << 7) /* framing error interrupt status */ +#define UART011_RTIS (1 << 6) /* receive timeout interrupt status */ +#define UART011_TXIS (1 << 5) /* transmit interrupt status */ +#define UART011_RXIS (1 << 4) /* receive interrupt status */ +#define UART011_DSRMIS (1 << 3) /* DSR interrupt status */ +#define UART011_DCDMIS (1 << 2) /* DCD interrupt status */ +#define UART011_CTSMIS (1 << 1) /* CTS interrupt status */ +#define UART011_RIMIS (1 << 0) /* RI interrupt status */ + +#define UART011_OEIC (1 << 10) /* overrun error interrupt clear */ +#define UART011_BEIC (1 << 9) /* break error interrupt clear */ +#define UART011_PEIC (1 << 8) /* parity error interrupt clear */ +#define UART011_FEIC (1 << 7) /* framing error interrupt clear */ +#define UART011_RTIC (1 << 6) /* receive timeout interrupt clear */ +#define UART011_TXIC (1 << 5) /* transmit interrupt clear */ +#define UART011_RXIC (1 << 4) /* receive interrupt clear */ +#define UART011_DSRMIC (1 << 3) /* DSR interrupt clear */ +#define UART011_DCDMIC (1 << 2) /* DCD interrupt clear */ +#define UART011_CTSMIC (1 << 1) /* CTS interrupt clear */ +#define UART011_RIMIC (1 << 0) /* RI interrupt clear */ + +#define UART011_BASE_ADDR 0x9000000 //!< 寄存器基地址 +#define UART011_FREQ 0x0 //!< 频率 +#define UART011_DEFAULT_BAUD 115200 +void uart_set_baud(int baud) +{ + uint32_t fi_val = UART011_FREQ * 4 / baud; + + write_reg32(UART011_BASE_ADDR + UART011_FBRD, fi_val & 0x3f); + write_reg32(UART011_BASE_ADDR + UART011_IBRD, fi_val >> 6); +} +void uart_write_byte(uint8_t byte) +{ + int i = 3000000; + + while (i--) + { + if (!(read_reg32(UART011_BASE_ADDR + UART01x_FR) & UART01x_FR_TXFF)) + { + break; + } + } + write_reg32(UART011_BASE_ADDR + UART01x_DR, byte); +} +void uart_write_bytes(uint8_t *bytes, int len) +{ + for (int i = 0; i < len; i++) + { + uart_write_byte((bytes[i])); + } +} +void uart_write_str(const char *str) +{ + for (int i = 0; str[i]; i++) + { + uart_write_byte((str[i])); + } +} +void uart_init(void) +{ + write_reg32(UART011_BASE_ADDR + UART011_CR, UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_RXE); + if (UART011_FREQ) + { + uart_set_baud(UART011_DEFAULT_BAUD); + } + write_reg32(UART011_BASE_ADDR + UART011_LCRH, UART011_LCRH_WLEN_8); + write_reg32(UART011_BASE_ADDR + UART011_IMSC, 0); + + int i = 4000000; + + while (i--) + { + if (!(read_reg32(UART011_BASE_ADDR + UART01x_FR) & UART01x_FR_BUSY)) + { + break; + } + } +} diff --git a/mkrtos_bootstrap/bsp/AARCH64_QEMU/uart.h b/mkrtos_bootstrap/bsp/AARCH64_QEMU/uart.h new file mode 100644 index 000000000..7c1477a6e --- /dev/null +++ b/mkrtos_bootstrap/bsp/AARCH64_QEMU/uart.h @@ -0,0 +1,4 @@ +#pragma once + +void uart_init(void); +void uart_write_str(const char *str); diff --git a/mkrtos_bootstrap/bsp/SWM34S/link.lds b/mkrtos_bootstrap/bsp/SWM34S/link.lds index 9066c7073..d3a64ba7b 100755 --- a/mkrtos_bootstrap/bsp/SWM34S/link.lds +++ b/mkrtos_bootstrap/bsp/SWM34S/link.lds @@ -67,5 +67,5 @@ SECTIONS __StackTop = ORIGIN(RAM) + LENGTH(RAM); __StackLimit = __StackTop - SIZEOF(.stack_dummy); - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") + assert(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") } \ No newline at end of file diff --git a/mkrtos_bootstrap/inc/string.h b/mkrtos_bootstrap/inc/string.h old mode 100644 new mode 100755 index 84b595818..ac98f5c93 --- a/mkrtos_bootstrap/inc/string.h +++ b/mkrtos_bootstrap/inc/string.h @@ -1,11 +1,11 @@ #pragma once -static inline void memset(void *data, int val, int size) -{ - unsigned int *_d = data; +#include "types.h" - for (int i = 0; i < size; i++) - { - _d[0] = 0; - } -} +void *memccpy(void *dst, const void *src, int c, size_t count); +void memcpy(void *dst, void *src, size_t len); +void *memset(void *dst, char s, size_t count); +int strcmp(const char *s1, const char *s2); +char *strcpy(register char *s1, register const char *s2); +size_t strlen(const char *s); +char *strncpy(char *dest, const char *src, uint32_t n); \ No newline at end of file diff --git a/mkrtos_bootstrap/main.c b/mkrtos_bootstrap/main.c index cac88b90e..8e4c06c1e 100755 --- a/mkrtos_bootstrap/main.c +++ b/mkrtos_bootstrap/main.c @@ -2,9 +2,11 @@ #include #include +extern char cpio_start[]; +extern char cpio_end[]; int main(void) { - jump2kernel(); + jump2kernel((addr_t)cpio_start, (addr_t)cpio_end); while (1) ; } diff --git a/mkrtos_bootstrap/string.c b/mkrtos_bootstrap/string.c new file mode 100755 index 000000000..f3b2af3a0 --- /dev/null +++ b/mkrtos_bootstrap/string.c @@ -0,0 +1,65 @@ + +#include "types.h" +#include "string.h" +void *memccpy(void *dst, const void *src, int c, size_t count) +{ + char *a = dst; + const char *b = src; + while (count--) + { + *a++ = *b; + if (*b == c) + { + return (void *)a; + } + b++; + } + return 0; +} +void memcpy(void *dst, void *src, size_t len) +{ + register char *b_dst = dst; + register char *b_src = src; + for (; len; len--) + { + (*b_dst++) = (*b_src++); + } +} +void *memset(void *dst, char s, size_t count) +{ + register char *a = dst; + count++; /* this actually creates smaller code than using count-- */ + while (--count) + *a++ = s; + return dst; +} +int strcmp(const char *s1, const char *s2) +{ + while (*s1 && *s1 == *s2) + s1++, s2++; + return (*s1 - *s2); +} +char *strcpy(register char *s1, register const char *s2) +{ + register char *res = s1; + while ((*s1++ = *s2++)) + ; + return (res); +} +size_t strlen(const char *s) +{ + const char *t = s; + unsigned long word; + + if (!s) + return 0; + + for (; *s++;) + ; + return (size_t)(s - t) - 1; +} +char *strncpy(char *dest, const char *src, uint32_t n) +{ + memccpy(dest, src, 0, n); + return dest; +} diff --git a/mkrtos_configs/aarch64_qemu_defconfig b/mkrtos_configs/aarch64_qemu_defconfig new file mode 100644 index 000000000..314fc91ad --- /dev/null +++ b/mkrtos_configs/aarch64_qemu_defconfig @@ -0,0 +1,118 @@ + +# +# Knl config +# +CONFIG_KNL_INFO=y +CONFIG_KNL_TEXT_ADDR=0x1000 +CONFIG_KNL_TEXT_SIZE=0x100000 +CONFIG_KNL_DATA_ADDR=0x40000000 +CONFIG_KNL_DATA_SIZE=0x800000 +CONFIG_KNL_OFFSET=0x1000 +CONFIG_INIT_TASK_OFFSET=0x10000 +CONFIG_BOOTFS_OFFSET=0x02000000 +CONFIG_MK_MPU_CFG=n +CONFIG_FT_ADDR_NR=16 +CONFIG_SYS_SCHE_HZ=1000 +CONFIG_USER_ISR_START_NO=16 +CONFIG_IRQ_REG_TAB_SIZE=80 +CONFIG_REGION_NUM=8 +CONFIG_OBJ_MAP_TAB_SIZE=32 +CONFIG_OBJ_MAP_ENTRY_SIZE=32 +CONFIG_PRINTK_CACHE_SIZE=128 +# end of Knl config + +# +# Libc backend +# +CONFIG_FD_MAP_ROW_CN=16 +CONFIG_FD_MAP_ROW_NR=16 +# end of Libc backend + +# +# Sys util config +# +CONFIG_USING_SIG=n +CONFIG_SIG_THREAD_STACK_SIZE=512 +CONFIG_SIG_THREAD_PRIO=3 +# end of Sys util config + +# +# DFS: device virtual file system +# +CONFIG_RT_USING_DFS=y +CONFIG_DFS_USING_POSIX=y +CONFIG_DFS_USING_WORKDIR=y +# CONFIG_RT_USING_DFS_MNTTABLE is not set +CONFIG_DFS_FD_MAX=16 +CONFIG_RT_USING_DFS_V1=y +# CONFIG_RT_USING_DFS_V2 is not set +CONFIG_DFS_FILESYSTEMS_MAX=4 +CONFIG_DFS_FILESYSTEM_TYPES_MAX=4 +# CONFIG_RT_USING_DFS_ELMFAT is not set +CONFIG_RT_USING_DFS_DEVFS=y +# CONFIG_RT_USING_DFS_ROMFS is not set +# CONFIG_RT_USING_DFS_CROMFS is not set +# CONFIG_RT_USING_DFS_RAMFS is not set +# CONFIG_RT_USING_DFS_TMPFS is not set +# CONFIG_RT_USING_DFS_MQUEUE is not set +# end of DFS: device virtual file system + +# +# Device Drivers +# +# CONFIG_RT_USING_DM is not set +CONFIG_RT_USING_DEVICE_IPC=y +CONFIG_RT_UNAMED_PIPE_NUMBER=64 +# CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set +CONFIG_RT_USING_SERIAL=y +CONFIG_RT_USING_SERIAL_V1=y +# CONFIG_RT_USING_SERIAL_V2 is not set +CONFIG_RT_SERIAL_USING_DMA=y +CONFIG_RT_SERIAL_RB_BUFSZ=64 +# CONFIG_RT_USING_CAN is not set +# CONFIG_RT_USING_HWTIMER is not set +# CONFIG_RT_USING_CPUTIME is not set +# CONFIG_RT_USING_I2C is not set +# CONFIG_RT_USING_PHY is not set +CONFIG_RT_USING_PIN=y +# CONFIG_RT_USING_ADC is not set +# CONFIG_RT_USING_DAC is not set +# CONFIG_RT_USING_NULL is not set +# CONFIG_RT_USING_ZERO is not set +# CONFIG_RT_USING_RANDOM is not set +# CONFIG_RT_USING_PWM is not set +# CONFIG_RT_USING_MTD_NOR is not set +# CONFIG_RT_USING_MTD_NAND is not set +# CONFIG_RT_USING_PM is not set +# CONFIG_RT_USING_RTC is not set +# CONFIG_RT_USING_SDIO is not set +# CONFIG_RT_USING_SPI is not set +# CONFIG_RT_USING_WDT is not set +# CONFIG_RT_USING_AUDIO is not set +# CONFIG_RT_USING_SENSOR is not set +# CONFIG_RT_USING_TOUCH is not set +# CONFIG_RT_USING_LCD is not set +# CONFIG_RT_USING_HWCRYPTO is not set +# CONFIG_RT_USING_PULSE_ENCODER is not set +# CONFIG_RT_USING_INPUT_CAPTURE is not set +# CONFIG_RT_USING_DEV_BUS is not set +# CONFIG_RT_USING_WIFI is not set +# CONFIG_RT_USING_VIRTIO is not set + +# +# Using USB +# +# CONFIG_RT_USING_USB_HOST is not set +# CONFIG_RT_USING_USB_DEVICE is not set +# end of Using USB +# end of Device Drivers + +CONFIG_CPU_TYPE="aarch64_qemu" +CONFIG_RTT_DIR="./" +CONFIG_ARCH="aarch64" +CONFIG_BOARD_NAME="aarch64_qemu" +CONFIG_BUDDY_SLAB=y +CONFIG_SMP=y +CONFIG_CPU=4 +CONFIG_THREAD_BLOCK_SIZE=0x1000 +CONFIG_PAGE_SHIFT=12 diff --git a/mkrtos_img/CMakeLists.txt b/mkrtos_img/CMakeLists.txt index 8f08c4d5a..b132004cc 100755 --- a/mkrtos_img/CMakeLists.txt +++ b/mkrtos_img/CMakeLists.txt @@ -10,7 +10,7 @@ add_custom_target( srec_cat -output ${CMAKE_SOURCE_DIR}/build/output/kernel.img -binary ${CMAKE_SOURCE_DIR}/build/output/bootstrap -binary -offset 0x0 ${CMAKE_SOURCE_DIR}/build/output/mkrtos -binary -offset ${CONFIG_KNL_OFFSET} - ${CMAKE_SOURCE_DIR}/build/output/init -binary -offset ${CONFIG_INIT_TASK_OFFSET} + # ${CMAKE_SOURCE_DIR}/build/output/init -binary -offset ${CONFIG_INIT_TASK_OFFSET} ${CMAKE_SOURCE_DIR}/build/output/rootfs.cpio -binary -offset ${CONFIG_BOOTFS_OFFSET} COMMAND cp ${CMAKE_SOURCE_DIR}/build/output/kernel.img ${CMAKE_SOURCE_DIR}/build/output/kernel.bin @@ -23,9 +23,9 @@ add_custom_target( add_dependencies(mkrtos_img_dump bootstrap_dump mkrtos_dump - init_dump + # init_dump # app_dump - shell_dump + # shell_dump # fatfs_dump # cpiofs_dump # tcc_dump diff --git a/mkrtos_knl/CMakeLists.txt b/mkrtos_knl/CMakeLists.txt index 9be3d2836..350177af7 100755 --- a/mkrtos_knl/CMakeLists.txt +++ b/mkrtos_knl/CMakeLists.txt @@ -8,7 +8,6 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} \ -Wno-unused-variable \ -Wno-builtin-declaration-mismatch \ ") -set(CMAKE_ASM_FLAGS ${CMAKE_C_FLAGS}) message(编译参数:${CMAKE_C_FLAGS}) add_subdirectory(arch) @@ -37,7 +36,7 @@ add_dependencies(mkrtos.elf knl) add_dependencies(mkrtos.elf lib) set_target_properties(mkrtos.elf PROPERTIES -LINK_FLAGS "-T ${CMAKE_CURRENT_LIST_DIR}/link.lds -z max-page-size=0x1000 --gc-section ") +LINK_FLAGS "-T ${CMAKE_CURRENT_LIST_DIR}/arch/${CONFIG_ARCH}/link.lds -z max-page-size=0x1000 --gc-section ") add_custom_target( link_file_dump ALL @@ -48,8 +47,8 @@ add_custom_target( -DKNL_OFFSET=${CONFIG_KNL_OFFSET} # -DKNL_DATA_SIZE=$ENV{KNL_DATA_SIZE} -include ${CMAKE_SOURCE_DIR}/build/autoconf.h - -E -P -<${CMAKE_CURRENT_LIST_DIR}/link.lds.S> - ${CMAKE_CURRENT_LIST_DIR}/link.lds + -E -P -<${CMAKE_CURRENT_LIST_DIR}/arch/${CONFIG_ARCH}/link.lds.S> + ${CMAKE_CURRENT_LIST_DIR}/arch/${CONFIG_ARCH}/link.lds ) add_custom_target( @@ -59,10 +58,14 @@ add_custom_target( COMMAND mkdir -p ${CMAKE_SOURCE_DIR}/build/output COMMAND + mkdir -p ${CMAKE_SOURCE_DIR}/build/output/cpio + COMMAND cp mkrtos.bin ${CMAKE_SOURCE_DIR}/build/output/mkrtos COMMAND cp mkrtos.elf ${CMAKE_SOURCE_DIR}/build/output/mkrtos.elf COMMAND + cp mkrtos.elf ${CMAKE_SOURCE_DIR}/build/output/cpio/mkrtos.elf + COMMAND ${CMAKE_OBJDUMP} -s -S mkrtos.elf > ${CMAKE_SOURCE_DIR}/build/output/mkrtos.S COMMAND ${CMAKE_SIZE} mkrtos.elf diff --git a/mkrtos_knl/Kconfig b/mkrtos_knl/Kconfig index e3b86d3ee..ed0fd2d52 100644 --- a/mkrtos_knl/Kconfig +++ b/mkrtos_knl/Kconfig @@ -5,6 +5,23 @@ menuconfig KNL_INFO bool "knl info set" default y if KNL_INFO + config PAGE_SHIFT + int "page shift" + default 9 + config SMP + bool "support smp." + default n +if SMP + config CPU + int "CPU Core number." + default 1 +endif + config BUDDY_SLAB + bool "use BUDDY & SLAB" + default n + config THREAD_BLOCK_SIZE + hex "kthread block size" + default 0x400 config KNL_TEXT_ADDR hex "The first address of the kernel text section" default 0x8000000 diff --git a/mkrtos_knl/arch/CMakeLists.txt b/mkrtos_knl/arch/CMakeLists.txt index f97627f13..a4878ec8f 100755 --- a/mkrtos_knl/arch/CMakeLists.txt +++ b/mkrtos_knl/arch/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.13) -add_subdirectory(armv7m) +add_subdirectory(${ARCH}) diff --git a/mkrtos_knl/arch/aarch64/CMakeLists.txt b/mkrtos_knl/arch/aarch64/CMakeLists.txt new file mode 100755 index 000000000..e9aa79f6d --- /dev/null +++ b/mkrtos_knl/arch/aarch64/CMakeLists.txt @@ -0,0 +1,34 @@ +cmake_minimum_required(VERSION 3.13) + +file(GLOB deps *.c *.S) +list(REMOVE_ITEM deps ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/aarch64/link.lds.S) +add_library(arch STATIC ${deps}) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D__MPU_PRESENT=1 -DUSE_STDPERIPH_DRIVER=1 ") +message(=======${CONFIG_CPU_TYPE}) + +if (${CONFIG_CPU_TYPE} STREQUAL "aarch64_qemu" ) + + include_directories( + ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/${ARCH}/${CONFIG_CPU_TYPE} + ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/knl + ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/drv + ) + + add_subdirectory(${CONFIG_CPU_TYPE}) +endif() + +target_link_libraries( + arch + PUBLIC + knl_bsp +) +target_include_directories( + arch + PUBLIC + ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/inc + ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/lib + ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/knl + + +) diff --git a/mkrtos_knl/arch/aarch64/aarch64_ptregs.h b/mkrtos_knl/arch/aarch64/aarch64_ptregs.h new file mode 100644 index 000000000..207322217 --- /dev/null +++ b/mkrtos_knl/arch/aarch64/aarch64_ptregs.h @@ -0,0 +1,21 @@ +#pragma once + +/* + * pt_regs栈框,用来保存中断现场或者异常现场 + * + * pt_regs栈框通常位于进程的内核栈的顶部。 + * pt_regs栈框通常位于进程的内核栈的顶部。 + * 而sp的栈顶通常 紧挨着 pt_regs栈框,在pt_regs栈框下方。 + * 保存内容: + * x0 ~ x30 通用寄存器 + * sp + * pc + * pstate + */ +typedef struct pt_regs +{ + unsigned long regs[31]; + unsigned long sp; + unsigned long pc; + unsigned long pstate; +} pt_regs_t; diff --git a/mkrtos_knl/arch/aarch64/aarch64_qemu/CMakeLists.txt b/mkrtos_knl/arch/aarch64/aarch64_qemu/CMakeLists.txt new file mode 100755 index 000000000..c6f70412e --- /dev/null +++ b/mkrtos_knl/arch/aarch64/aarch64_qemu/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.13) + + +file(GLOB_RECURSE deps *.s *.S *.C *.c) +# list(APPEND deps ${bsp_src}) + +add_library(knl_bsp STATIC ${deps}) +target_include_directories( + knl_bsp + PUBLIC + ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/lib + ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/knl + ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/inc + + ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/${CONFIG_ARCH}/${CONFIG_CPU_TYPE} + ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/${CONFIG_ARCH}/ + +) diff --git a/mkrtos_knl/arch/aarch64/aarch64_qemu/arch.c b/mkrtos_knl/arch/aarch64/aarch64_qemu/arch.c new file mode 100644 index 000000000..cc06e17f3 --- /dev/null +++ b/mkrtos_knl/arch/aarch64/aarch64_qemu/arch.c @@ -0,0 +1,108 @@ +/** + * @file arch.c + * @author ATShining (1358745329@qq.com) + * @brief + * @version 0.1 + * @date 2023-09-25 + * + * @copyright Copyright (c) 2023 + * + */ +#include "arch.h" +#include "types.h" +#include "util.h" +#include "init.h" +#include "config.h" +#include "thread.h" +#include "mk_sys.h" +#include "mpu.h" +#include +#include +#include +#include +__ALIGN__(THREAD_BLOCK_SIZE) +static uint8_t thread_knl_stack[THREAD_BLOCK_SIZE] = {0}; +void *_estack = thread_knl_stack + THREAD_BLOCK_SIZE; + +/** + * 进行调度 + */ +void to_sche(void) +{ + // 开启pensv中断 + /*TODO:*/ +} +/** + * 进行一些系统的初始化 + */ +void sys_startup(void) +{ + /*TODO:*/ + init_arm_hyp(); + timer_init(arch_get_current_cpu_id()); +} +void sys_reset(void) +{ + /*TODO:*/ +} +void arch_disable_irq(int inx) +{ + /*TODO:*/ +} +void arch_enable_irq(int inx) +{ + /*TODO:*/ +} +uint32_t arch_get_sys_clk(void) +{ + /*TODO:*/ + return 0; +} +void arch_set_enable_irq_prio(int inx, int sub_prio, int pre_prio) +{ + /*TODO:*/ +} +extern char _data_boot[], _edata_boot[]; +extern char _text_boot[], _etext_boot[]; +extern char _text[], _etext[]; +extern char _rodata[], _erodata[]; +extern char _data[], _edata[]; +extern char _bss[], _ebss[]; +extern char _buddy_data_start[]; +extern char _buddy_data_end[]; + +static void print_mem(void) +{ + printk("MKRTOS image layout:\n"); + printk(" .text.boot: 0x%08lx - 0x%08lx (%6ld B)\n", + (unsigned long)_text_boot, (unsigned long)_etext_boot, + (unsigned long)(_etext_boot - _text_boot)); + printk(" .text.data: 0x%08lx - 0x%08lx (%6ld B)\n", + (unsigned long)_data_boot, (unsigned long)_edata_boot, + (unsigned long)(_edata_boot - _data_boot)); + printk(" .text: 0x%08lx - 0x%08lx (%6ld B)\n", + (unsigned long)_text, (unsigned long)_etext, + (unsigned long)(_etext - _text)); + printk(" .rodata: 0x%08lx - 0x%08lx (%6ld B)\n", + (unsigned long)_rodata, (unsigned long)_erodata, + (unsigned long)(_erodata - _rodata)); + printk(" .data: 0x%08lx - 0x%08lx (%6ld B)\n", + (unsigned long)_data, (unsigned long)_edata, + (unsigned long)(_edata - _data)); + printk(" .bss: 0x%08lx - 0x%08lx (%6ld B)\n", + (unsigned long)_bss, (unsigned long)_ebss, + (unsigned long)(_ebss - _bss)); + printk(" .buddy: 0x%08lx - 0x%08lx (%6ld B)\n", + (unsigned long)_buddy_data_start, (unsigned long)_buddy_data_end, + (unsigned long)(_buddy_data_end - _buddy_data_start)); +} + +void arch_init(void) +{ + printk("MKRTOS running on EL:%d\n", arch_get_currentel() >> 2); + print_mem(); + psci_init(); + gic_init(arm_gicv2_get_global(), + 0x08000000, 0x08010000); /*TODO:*/ +} +INIT_LOW_HARD(arch_init); diff --git a/mkrtos_knl/arch/aarch64/aarch64_qemu/arch.h b/mkrtos_knl/arch/aarch64/aarch64_qemu/arch.h new file mode 100755 index 000000000..54ffa80e4 --- /dev/null +++ b/mkrtos_knl/arch/aarch64/aarch64_qemu/arch.h @@ -0,0 +1,167 @@ +/** + * @file arch.h + * @author ATShining (1358745329@qq.com) + * @brief + * @version 0.1 + * @date 2023-10-04 + * + * @copyright Copyright (c) 2023 + * + */ +#pragma once + +#include "types.h" +#include "arch.h" +#include +#include +#define LOG_INTR_NO 37 // USART1_IRQn + +#define _barrier() __asm__ __volatile__("" : : : "memory") +#define _dmb(ins) \ + asm volatile("dmb " #ins : : : "memory") +#define _isb() asm volatile("isb" : : : "memory") +#define _dsb(ins) \ + asm volatile("dsb " #ins : : : "memory") + +#define read_reg(addr) (*((volatile umword_t *)(addr))) +#define write_reg(addr, data) \ + do \ + { \ + _barrier(); \ + (*((volatile umword_t *)(addr))) = data; \ + _barrier(); \ + } while (0) + +#define read_reg32(addr) (*((volatile uint32_t *)(addr))) +#define write_reg32(addr, data) \ + do \ + { \ + _barrier(); \ + (*((volatile uint32_t *)(addr))) = (uint32_t)data; \ + _barrier(); \ + } while (0) + +//! 读取系统寄存器 +#define read_sysreg(reg) ({ \ + unsigned long _val; \ + asm volatile("mrs %0, " #reg \ + : "=r"(_val)); \ + _val; \ +}) +//! 写入系统寄存器 +#define write_sysreg(val, reg) ({ \ + unsigned long _val = (unsigned long)val; \ + asm volatile("msr " #reg ", %x0" ::"rZ"(_val)); \ +}) + +static inline uint64_t arch_get_currentel(void) +{ + unsigned long _val; + + asm volatile("mrs %0, CurrentEL" + : "=r"(_val)); + return _val; +} +static inline int arch_get_current_cpu_id(void) +{ + return read_sysreg(mpidr_el1) & 0XFFUL; +} + +#define is_run_knl() \ + ({ \ + /*TODO:*/ \ + }) + +void to_sche(void); + +#define get_sp() ( \ + { \ + mword_t sp; \ + do \ + { \ + asm volatile("mov %0, sp" : "=r"(sp)); \ + } while (0); \ + sp; \ + }) +#define set_sp(sp) ( \ + { \ + do \ + { \ + asm volatile("mov sp, %0" : : "r"(sp)); \ + } while (0); \ + }) +static inline umword_t arch_get_sp(void) +{ + return get_sp(); +} +static inline umword_t arch_get_isr_no(void) +{ + /*TODO:获取中断号*/ + return 0; +} +static inline void arch_set_knl_sp(umword_t sp) +{ + set_sp(sp); +} +static inline umword_t arch_get_knl_sp(void) +{ + return get_sp(); +} +static inline void arch_set_user_sp(umword_t sp) +{ +} +static inline umword_t arch_get_user_sp(void) +{ + return 0; +} +void arch_disable_irq(int inx); +void arch_enable_irq(int inx); +void arch_set_enable_irq_prio(int inx, int sub_prio, int pre_prio); + +/** + * 开中断 + */ +#define sti() \ + do \ + { \ + asm volatile( \ + "msr daifclr, #3" \ + : \ + : \ + : "memory"); \ + } while (0) + +/** + * 关中断 + */ +#define cli() \ + do \ + { \ + asm volatile( \ + "msr daifset, #3" \ + : \ + : \ + : "memory"); \ + } while (0) + +static inline __attribute__((optimize(0))) void preemption(void) +{ + sti(); + cli(); +} + +static inline umword_t intr_status(void) +{ + umword_t ret; + + asm volatile("mrs %0, daif" : "=r"(ret)); + return !(ret & 0xc0); +} + +void sys_startup(void); +void sys_reset(void); + +// systick.c +umword_t sys_tick_cnt_get(void); + +uint32_t arch_get_sys_clk(void); diff --git a/mkrtos_knl/arch/aarch64/aarch64_qemu/entry.S b/mkrtos_knl/arch/aarch64/aarch64_qemu/entry.S new file mode 100644 index 000000000..888ad784b --- /dev/null +++ b/mkrtos_knl/arch/aarch64/aarch64_qemu/entry.S @@ -0,0 +1,118 @@ +#include +#include +.section .rodata +.align 3 +.globl string1 +string1: + .string "Booting at EL" + +/* 8字节对齐,否则会出错*/ +.align 3 +.globl sp_addr +.section ".data.boot" +sp_addr: + .quad per_cpu_stack + THREAD_BLOCK_SIZE - 8 - PT_REGS_SIZE //pt regs is 320 bytes. +.align 3 +.globl cpio_images +.section ".data.boot" +cpio_images: + .quad 0 //pt regs is 320 bytes. + +.align 3 +.global cpu_jump_addr +.section ".data.boot" +cpu_jump_addr: + .zero (32) //TODO: cpu_num*MWORD_BYTES + +.align 3 +.global per_cpu_stack_addr +.section ".data.boot" +per_cpu_stack_addr: + .zero (32) //TODO: cpu_num*MWORD_BYTES + +.section ".text.boot" +.globl _start +_start: + msr daifset, #0xf // 关闭中断 + mov x9, x0 +#ifdef CONFIG_DEBUG_ON_EARLY_ASM + /* init uart and print the string*/ + bl __init_uart +#endif + + mrs x5, CurrentEL + cmp x5, #CurrentEL_EL3 + b.eq el3_entry //进入el3的处理函数 + b el2_entry + +el3_entry: +#ifdef CONFIG_DEBUG_ON_EARLY_ASM + bl print_el +#endif + ldr x0, =SCTLR_EL2_VALUE_MMU_DISABLED + msr sctlr_el2, x0 + + ldr x0, =(1<<31)|(1<<4)|(1<<29) + msr hcr_el2, x0 + + ldr x0, =((1UL) | (1UL<<7) | (1UL<<8) | (1UL<<10)) + msr scr_el3, x0 + + ldr x0, =SPSR_EL2 + msr spsr_el3, x0 + + adr x0, el2_entry + msr elr_el3, x0 + + eret + +el2_entry: //进入el2 + + + /* Generic timers. */ + //mrs x0, cnthctl_el2 + //orr x0, x0, #3 // Enable EL1 physical timers + //msr cnthctl_el2, x0 + //msr cntvoff_el2, xzr // Clear virtual offset + + mrs x0, cpacr_el1 + orr x0, x0, 0x3 << 20 + msr cpacr_el1, x0 + + /* 设置异常向量表基地址到vbar寄存器 */ + ldr x5, =vectors + msr vbar_el2, x5 + isb + + //进入多核启动流程 + mrs x0, mpidr_el1 // 读取该寄存器获取处理器id + and x0, x0,#0xFF // Check processor id + cbz x0, master // Hang for all non-primary CPU + + //spin table + ldr x1, = cpu_jump_addr + lsl x2, x0, MWORD_SHIFT +spin_jump: + ldr x3, [x1, x2] + cbz x3, spin_jump + ldr x4, = per_cpu_stack_addr + ldr x4, [x4, x2] //获取sp启动的值 + mov sp, x4 //cpu启动的sp地址 + br x3 + b . +master: + ldr x0, = cpio_images + str x9, [x0, #0] + /* set sp to top of init_task_union */ + ldr x8, =sp_addr + ldr x9, [x8] + mov sp, x9 + bl boot_mapping +proc_hang: + b proc_hang // should never come here + +.globl jump_kenel_main +jump_kenel_main: + ldr x1, = start_kernel + br x1 + b . diff --git a/mkrtos_knl/arch/aarch64/aarch64_qemu/mk_sys.h b/mkrtos_knl/arch/aarch64/aarch64_qemu/mk_sys.h new file mode 100755 index 000000000..20a57f561 --- /dev/null +++ b/mkrtos_knl/arch/aarch64/aarch64_qemu/mk_sys.h @@ -0,0 +1,6 @@ +#ifndef __SYS_H +#define __SYS_H + + + +#endif diff --git a/mkrtos_knl/arch/aarch64/aarch64_qemu/vector.S b/mkrtos_knl/arch/aarch64/aarch64_qemu/vector.S new file mode 100755 index 000000000..03d01c71c --- /dev/null +++ b/mkrtos_knl/arch/aarch64/aarch64_qemu/vector.S @@ -0,0 +1,268 @@ +#include +#include + +#define BAD_SYNC 0 +#define BAD_IRQ 1 +#define BAD_FIQ 2 +#define BAD_ERROR 3 + + + /*保存x0~x29,x30(lr),sp, elr, spsr保存到 栈中 + */ + .macro kernel_entry el + /* + SP指向了栈底, S_FRAME_SIZE表示一个栈框的大小. + 定义一个struct pt_regs来描述一个栈框, + 用在异常发生时保存上下文. + */ + sub sp, sp, #S_FRAME_SIZE + + /* + 保存通用寄存器x0~x29到栈框里pt_regs->x0~x29 + */ + 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] + + /* x21: 栈顶 的位置*/ + add x21, sp, #S_FRAME_SIZE + mov x0, sp + + mrs x22, elr_el2 + mrs x23, spsr_el2 + + /* 把lr保存到pt_regs->lr, 把sp保存到pt_regs->sp位置*/ + stp lr, x21, [sp, #S_LR] + /* 把elr_el1保存到pt_regs->pc中 + 把spsr_elr保存到pt_regs->pstate中*/ + stp x22, x23, [sp, #S_PC] + .endm + +/* + 恢复异常发生时保存下来的上下文 + */ + .macro kernel_exit el + /* 从pt_regs->pc中恢复elr_el1, + 从pt_regs->pstate中恢复spsr_el1 + */ + ldp x21, x22, [sp, #S_PC] // load ELR, SPSR + msr elr_el2, x21 // set up the return data + msr spsr_el2, x22 + + 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] + + /* 从pt_regs->lr中恢复lr*/ + ldr lr, [sp, #S_LR] + add sp, sp, #S_FRAME_SIZE // restore sp + eret // return to kernel + .endm + +/* + 处理无效的异常向量 + */ + .macro inv_entry el, reason + //kernel_entry el + mov x0, sp + mov x1, #\reason + mrs x2, esr_el2 + b bad_mode + .endm + +/* + vector table entry + 每个表项是128字节, align 7表示128字节对齐 + */ + .macro vtentry label + .align 7 + b \label + .endm + +/* + * Vector Table + * + * ARM64的异常向量表一共占用2048个字节 + * 分成4组,每组4个表项,每个表项占128字节 + * 参见ARMv8 spec v8.6第D1.10节 + * align 11表示2048字节对齐 + */ +.align 11 +.global vectors +.section ".text.boot" +vectors: + /* Current EL with SP0 + 当前系统运行在EL1时使用EL0的栈指针SP + 这是一种异常错误的类型 + */ + vtentry el1_sync_invalid + vtentry el1_irq_invalid + vtentry el1_fiq_invalid + vtentry el1_error_invalid + + /* Current EL with SPx + 当前系统运行在EL1时使用EL1的栈指针SP + 这说明系统在内核态发生了异常 + + Note: 我们暂时只实现IRQ中断 + */ + + vtentry el1_sync_invalid + vtentry el1_irq + vtentry el1_fiq_invalid + vtentry el1_error_invalid + + /* Lower EL using AArch64 + 在用户态的aarch64的程序发生了异常 + */ + vtentry el1_sync_invalid + vtentry el1_irq + vtentry el0_fiq_invalid + vtentry el0_error_invalid + + /* Lower EL using AArch32 + 在用户态的aarch32的程序发生了异常 + */ + vtentry el0_sync_invalid + vtentry el0_irq_invalid + vtentry el0_fiq_invalid + vtentry el0_error_invalid +el1_sync_invalid: + kernel_entry 2 + //mrs x25, ESR_EL2 + //lsr x24, x25, 26 + //cmp x24, 0x16 + //b.eq el2_svc + //inv_entry 0, BAD_SYNC + //el2_svc: + // mov x0, sp + // bl el2_svc_handler + bl thread_sync_entry + b ret_to_user + +el1_irq_invalid: + inv_entry 1, BAD_IRQ +el1_fiq_invalid: + inv_entry 1, BAD_FIQ +el1_error_invalid: + inv_entry 1, BAD_ERROR +el0_sync_invalid: + inv_entry 0, BAD_SYNC +el0_irq_invalid: + inv_entry 0, BAD_IRQ +el0_fiq_invalid: + inv_entry 0, BAD_FIQ +el0_error_invalid: + inv_entry 0, BAD_ERROR +tsk .req x28 // current thread_info + + .macro get_thread_info, rd + mov \rd, sp + and \rd, \rd, #(~(4096 - 1)) // top of stack + .endm +el1_irq: + kernel_entry 2 + bl entry_handler + get_thread_info tsk +// bl 2f +//1: +// kernel_exit 2 +//2: +// mov x24, lr + //bl sched_printf + bl SysTick_Handler + kernel_exit 2 +// ret x24 + // + +//string_test: +// .string "t" + +.global trigger_alignment +trigger_alignment: + ldr x0, =0x80002 + str wzr, [x0] + +/* + 对于用户进程,暂时还没实现 + */ +.align 2 +.global ret_to_user +ret_to_user: + kernel_exit 2 + //inv_entry 0, BAD_ERROR +/* + 对于内核线程: + x19保存了进程回调函数的入口 + x20保存进程的回调函数的参数 + 对于用户线程: + x19为零时,跳转到ret_to_user执行 + */ +.align 2 +.global ret_form_run +ret_form_run: + bl sched_tail + cbz x19, 1f + mov x0, x20 + blr x19 +1: + //ldr x19, =test_user_stack + //add x19, x19, #(4096 - 8) + //msr sp_el1, x19 + b ret_to_user + +/* 进程切换: 保存prev进程的上下文,并且恢复next进程 +的上下文 + cpu_switch_to(struct cpu_context *prev, + struct cpu_context *next); + +需要保存的上下文: x19 ~ x29, sp, lr +保存到进程的task_struct->cpu_context + */ +.align +.global cpu_switch_to +cpu_switch_to: + mov x8, x0 + mov x9, sp + stp x19, x20, [x8], #16 + stp x21, x22, [x8], #16 + stp x23, x24, [x8], #16 + stp x25, x26, [x8], #16 + stp x27, x28, [x8], #16 + stp x29, x9, [x8], #16 + str lr, [x8] + + mov x8, x1 + ldp x19, x20, [x8], #16 + ldp x21, x22, [x8], #16 + ldp x23, x24, [x8], #16 + ldp x25, x26, [x8], #16 + ldp x27, x28, [x8], #16 + ldp x29, x9, [x8], #16 + ldr lr, [x8] + mov sp, x9 + ret diff --git a/mkrtos_knl/arch/aarch64/arm_gicv2.c b/mkrtos_knl/arch/aarch64/arm_gicv2.c new file mode 100644 index 000000000..897bfc996 --- /dev/null +++ b/mkrtos_knl/arch/aarch64/arm_gicv2.c @@ -0,0 +1,10 @@ +#include + +static gic_t m_irq; + + +gic_t *arm_gicv2_get_global(void) +{ + return &m_irq; +} + diff --git a/mkrtos_knl/arch/aarch64/arm_gicv2.h b/mkrtos_knl/arch/aarch64/arm_gicv2.h new file mode 100644 index 000000000..bf127f0ff --- /dev/null +++ b/mkrtos_knl/arch/aarch64/arm_gicv2.h @@ -0,0 +1,290 @@ +#pragma once + +#include +#include +#include +#include +#include +// #include +/* + * ID0-ID15,分配给SGI (一般会将0-7给REE,8-15给TEE) + * ID16-ID31,分配给PPI + * ID32-ID1019,分配给SPI + * ID1020-ID1023,特殊中断号 + * ID1024-ID8191,reserved + * 8192及其以上,LPI + */ +typedef struct gic +{ + uint16_t irqs_number; //!< 支持的irq数量 + + addr_t disp_base_addr; //!< 分发器起始地址 + addr_t inter_base_addr; //!< 接口起始地址 +} gic_t; + +// #define GIC2_BASE (0xFF840000) +// #define GIC2_GICD_BASE (GIC2_BASE + 0x1000) + +#define GICD_CTLR(GIC2_GICD_BASE) (0x0 + GIC2_GICD_BASE) +#define GICD_TYPER(GIC2_GICD_BASE) (0x4 + GIC2_GICD_BASE) +#define GICD_IIDR(GIC2_GICD_BASE) (0x8 + GIC2_GICD_BASE) +#define GICD_IGROUPRn(GIC2_GICD_BASE) (0x80 + GIC2_GICD_BASE) +#define GICD_ISENABLERn(GIC2_GICD_BASE) (0x100 + GIC2_GICD_BASE) +#define GICD_ICENABLERn(GIC2_GICD_BASE) (0x180 + GIC2_GICD_BASE) +#define GICD_ISPENDRn(GIC2_GICD_BASE) (0x200 + GIC2_GICD_BASE) +#define GICD_ICPENDRn(GIC2_GICD_BASE) (0x280 + GIC2_GICD_BASE) +#define GICD_ISACTIVERn(GIC2_GICD_BASE) (0x300 + GIC2_GICD_BASE) +#define GICD_ICACTIVERn(GIC2_GICD_BASE) (0x380 + GIC2_GICD_BASE) +#define GICD_IPRIORITYRn(GIC2_GICD_BASE) (0x400 + GIC2_GICD_BASE) +#define GICD_ITARGETSRn(GIC2_GICD_BASE) (0x800 + GIC2_GICD_BASE) +#define GICD_ICFGRn(GIC2_GICD_BASE) (0xC00 + GIC2_GICD_BASE) +#define GICD_SGIR(GIC2_GICD_BASE) (0xf00 + GIC2_GICD_BASE) +#define GICD_CPENDSGIRn(GIC2_GICD_BASE) (0xf10 + GIC2_GICD_BASE) +#define GICD_SPENDSGIRn(GIC2_GICD_BASE) (0xf20 + GIC2_GICD_BASE) + +// #define (GIC2_GICC_BASE) (GIC2_BASE + 0x2000) +#define GICC_CTLR(GIC2_GICC_BASE) (0x0 + GIC2_GICC_BASE) +#define GICC_PMR(GIC2_GICC_BASE) (0x4 + GIC2_GICC_BASE) +#define GICC_BPR(GIC2_GICC_BASE) (0x8 + GIC2_GICC_BASE) +#define GICC_IAR(GIC2_GICC_BASE) (0xc + GIC2_GICC_BASE) +#define GICC_EOIR(GIC2_GICC_BASE) (0x10 + GIC2_GICC_BASE) +#define GICC_RPR(GIC2_GICC_BASE) (0x14 + GIC2_GICC_BASE) +#define GICC_HPPIR(GIC2_GICC_BASE) (0x18 + GIC2_GICC_BASE) +#define GICC_APRn(GIC2_GICC_BASE) (0xd0 + GIC2_GICC_BASE) +#define GICC_IIDR(GIC2_GICC_BASE) (0x00FC + GIC2_GICC_BASE) + +#define MAX_INTR_NO 1020 + +static inline void gic2_set_disp_cpu(gic_t *irq, uint64_t cpu_mask) +{ + write_reg32(GICD_SGIR(irq->disp_base_addr), + read_reg32(GICD_SGIR(irq->disp_base_addr)) | + ((cpu_mask & 0xff) << 16UL)); +} +static inline void gic2_clear_disp_cpu(gic_t *irq, uint8_t cpu_mask) +{ + write_reg32(GICD_SGIR(irq->disp_base_addr), + read_reg32(GICD_SGIR(irq->disp_base_addr)) & + ((~(cpu_mask & 0xff)) << 16UL)); +} +static inline void gic2_set_unmask(gic_t *irq, uint64_t inx) +{ + assert(inx < MAX_INTR_NO); + void *addr = (void *)(GICD_ISENABLERn(irq->disp_base_addr) + ((inx >> 5) << 2)); + uint32_t tmp = read_reg32(addr); + uint32_t bit_inx = inx % 32; + + MK_CLR_BIT(tmp, bit_inx); + tmp |= (1) << bit_inx; + write_reg32((uint32_t *)addr, tmp); +} +static inline void gic2_set_mask(gic_t *irq, uint64_t inx) +{ + assert(inx < MAX_INTR_NO); + void *addr = (void *)(GICD_ICENABLERn(irq->disp_base_addr) + ((inx >> 5) << 2)); + uint32_t tmp = read_reg32(addr); + uint32_t bit_inx = inx % 32; + + MK_CLR_BIT(tmp, bit_inx); + tmp |= (1) << bit_inx; + write_reg32((uint32_t *)addr, tmp); +} +static inline bool_t gic2_get_mask(gic_t *irq, uint64_t inx) +{ + assert(inx < MAX_INTR_NO); + void *addr = (void *)(GICD_ISENABLERn(irq->disp_base_addr) + + ((inx >> 5) << 2)); + uint32_t tmp = read_reg32((uint32_t *)addr); + uint32_t bit_inx = inx % 32; + + return !!((tmp >> bit_inx) & 0x1ul); +} +static inline void gic2_set_active(gic_t *irq, uint64_t inx) +{ + assert(inx < MAX_INTR_NO); + void *addr = (void *)(GICD_ISACTIVERn(irq->disp_base_addr) + ((inx >> 5) << 2)); + uint32_t tmp = read_reg32(addr); + uint32_t bit_inx = inx % 32; + + MK_CLR_BIT(tmp, bit_inx); + tmp |= (1) << bit_inx; + write_reg32((uint32_t *)addr, tmp); +} +static inline void gic2_clear_active(gic_t *irq, uint64_t inx) +{ + assert(inx < MAX_INTR_NO); + void *addr = (void *)(GICD_ICACTIVERn(irq->disp_base_addr) + ((inx >> 5) << 2)); + uint32_t tmp = read_reg32(addr); + uint32_t bit_inx = inx % 32; + + MK_CLR_BIT(tmp, bit_inx); + tmp |= (1) << bit_inx; + write_reg32((uint32_t *)addr, tmp); +} +static inline void gic2_set_pending(gic_t *irq, uint64_t inx) +{ + assert(inx < MAX_INTR_NO); + void *addr = (void *)(GICD_ISPENDRn(irq->disp_base_addr) + ((inx >> 5) << 2)); + uint32_t tmp = read_reg32(addr); + uint32_t bit_inx = inx % 32; + + MK_CLR_BIT(tmp, bit_inx); + tmp |= (1) << bit_inx; + write_reg32((uint32_t *)addr, tmp); +} +static inline void gic2_clear_pending(gic_t *irq, uint64_t inx) +{ + assert(inx < MAX_INTR_NO); + void *addr = (void *)(GICD_ICPENDRn(irq->disp_base_addr) + ((inx >> 5) << 2)); + uint32_t tmp = read_reg32(addr); + uint32_t bit_inx = inx % 32; + + MK_CLR_BIT(tmp, bit_inx); + tmp |= (1) << bit_inx; + write_reg32((uint32_t *)addr, tmp); +} + +static inline void gic2_set_target_cpu(gic_t *irq, uint64_t inx, uint64_t target_cpu) +{ + assert(inx < MAX_INTR_NO); + // assert(target_cpu < 8); + void *addr = (void *)(GICD_ITARGETSRn((irq->disp_base_addr)) + + ((inx >> 2) << 2)); + uint32_t bit_inx = inx % 4; + uint32_t tmp = read_reg32((uint32_t *)addr); + + tmp &= ~(0xffUL << (bit_inx << 3)); + tmp |= target_cpu << (bit_inx << 3); + write_reg32((uint32_t *)addr, tmp); + tmp = read_reg32((uint32_t *)addr); +} +static inline uint64_t gic2_get_target_cpu(gic_t *irq, uint64_t inx) +{ + assert(inx < MAX_INTR_NO); + void *addr = (void *)(GICD_ITARGETSRn(irq->disp_base_addr) + + ((inx >> 2) << 2)); + uint32_t bit_inx = inx % 4; + uint32_t tmp = read_reg32((uint32_t *)addr); + + return (tmp >> (bit_inx << 3)) & 0xff; +} +static inline void gic2_set_edge_mode(gic_t *irq, int inx, int mode) +{ + uint32_t tmp = read_reg32(GICD_ICFGRn(irq->disp_base_addr) + + ((inx >> 4) << 2)); + + tmp &= ~(0x3ul << ((inx % 16) << 1)); + tmp |= (!!mode << 1) << ((inx % 16) << 1); + write_reg32(GICD_ICFGRn(irq->disp_base_addr) + + ((inx >> 4) << 2), + tmp); +} +static inline int gic2_get_edge_mode(gic_t *irq, int inx) +{ + uint32_t tmp = read_reg32(GICD_ICFGRn(irq->disp_base_addr) + + ((inx >> 4) << 2)); + + return ((tmp >> ((inx % 16) << 1)) & 0x3UL) >> 1; +} +static inline void gic_enable(gic_t *irq) +{ + write_reg32(GICD_CTLR(irq->disp_base_addr), TRUE); +} +static inline void gic_disable(gic_t *irq) +{ + write_reg32(GICD_CTLR(irq->disp_base_addr), FALSE); +} +static inline void gic2_set_prio(gic_t *irq, int inx, uint64_t prio) +{ + uint32_t tmp = read_reg32(GICD_IPRIORITYRn(irq->disp_base_addr) + + ((inx >> 2) << 2)); + + tmp &= ~(0xffUL << ((inx % 4) << 3)); + tmp |= (prio & 0xffUL) << ((inx % 4) << 3); + write_reg32(GICD_IPRIORITYRn(irq->disp_base_addr) + + ((inx >> 2) << 2), + tmp); +} +static inline uint8_t gic2_get_prio(gic_t *irq, int inx) +{ + uint32_t tmp = read_reg32(GICD_IPRIORITYRn(irq->disp_base_addr) + + ((inx >> 2) << 2)); + + return ((tmp) >> ((inx % 4) << 3)) & 0xffUL; +} + +// cpu inter +static inline void gic2_cpu_enable(gic_t *irq) +{ + write_reg32(GICC_CTLR(irq->inter_base_addr), TRUE); +} +static inline void gic2_cpu_disable(gic_t *irq) +{ + write_reg32(GICC_CTLR(irq->inter_base_addr), FALSE); +} + +static inline void gic_dist_init(gic_t *irq) +{ + gic_disable(irq); + + for (int i = 32; i < irq->irqs_number; i++) + { + gic2_set_unmask(irq, i); + gic2_set_edge_mode(irq, i, 0); + gic2_clear_active(irq, i); + } + for (int i = 0; i < 16; i++) + { + gic2_set_unmask(irq, i); + } + + gic_enable(irq); +} +static inline void gic_inter_init(gic_t *irq) +{ + + for (int i = 0; i < 32; i++) + { + gic2_set_prio(irq, i, 0xa0); + } + + write_reg32(GICC_PMR(irq->inter_base_addr), 0xf0UL); + gic2_cpu_enable(irq); +} +static inline void gic2_eoi_irq(gic_t *irq, int inx) +{ + write_reg32(GICC_EOIR(irq->inter_base_addr), inx); +} +static inline void gic_init(gic_t *irq, addr_t disp_addr, addr_t inter_addr) +{ + irq->irqs_number = ((read_reg32(GICD_TYPER(disp_addr)) & 0x1ful) + 1) * 32; + if (irq->irqs_number > MAX_INTR_NO) + { + irq->irqs_number = MAX_INTR_NO; + } + irq->disp_base_addr = disp_addr; + irq->inter_base_addr = inter_addr; + + printk("irqs_number %d, disp_base 0x%lx inter_base 0x%lx.\n", irq->irqs_number, irq->disp_base_addr, irq->inter_base_addr); + + gic_dist_init(irq); + gic_inter_init(irq); +} +gic_t *arm_gicv2_get_global(void); +// static inline void gic_handle_irq(void) +// { +// extern gic_t m_irq; + +// do +// { +// uint32_t irqstat = +// read_reg32(GICC_IAR(m_irq.inter_base_addr)); +// uint32_t irqnr = irqstat & 0x3ff; + +// if (irqnr == 30) +// handle_timer_irq(); + +// gic2_eoi_irq(&m_irq, irqnr); + +// } while (0); +// } diff --git a/mkrtos_knl/arch/aarch64/asm/arm_local_reg.h b/mkrtos_knl/arch/aarch64/asm/arm_local_reg.h new file mode 100755 index 000000000..e2aa614e6 --- /dev/null +++ b/mkrtos_knl/arch/aarch64/asm/arm_local_reg.h @@ -0,0 +1,52 @@ +#include "asm/base.h" + +/* + * ARM Local register for PI + * see 6.5.2 + */ + +#define ARM_CONTROL (ARM_LOCAL_BASE + 0x0) +#define CORE_IRQ_CONTROL (ARM_LOCAL_BASE + 0xc) +#define PMU_CONTROL_SET (ARM_LOCAL_BASE + 0x10) +#define PMU_CONTROL_CLR (ARM_LOCAL_BASE + 0x14) +#define PERI_IRQ_ROUTE0 (ARM_LOCAL_BASE + 0x24) +#define AXI_QUIET_TIME (ARM_LOCAL_BASE + 0x30) +#define LOCAL_TIMER_CONTROL (ARM_LOCAL_BASE + 0x34) +#define LOCAL_TIMER_IRQ (ARM_LOCAL_BASE + 0x38) + +#define TIMER_CNTRL0 (ARM_LOCAL_BASE + 0x40) +#define TIMER_CNTRL1 (ARM_LOCAL_BASE + 0x44) +#define TIMER_CNTRL2 (ARM_LOCAL_BASE + 0x48) +#define TIMER_CNTRL3 (ARM_LOCAL_BASE + 0x4c) +/* Secure Physical Timer Event for IRQ */ +#define CNT_PS_IRQ (1 << 0) +/* Nonsecure Physical Timer Event for IRQ */ +#define CNT_PNS_IRQ (1 << 1) +/* Hypervisor Physical Timer Event for IRQ */ +#define CNT_HP_IRQ (1 << 2) +/* Virtual Timer Event for IRQ */ +#define CNT_V_IRQ (1 << 3) +/* Secure Physical Timer Event for FIQ */ +#define CNT_PS_IRQ_FIQ (1 << 4) +/* Nonsecure Physical Timer Event for FIQ */ +#define CNT_PNS_IRQ_FIQ (1 << 5) +/* Hypervisor Physical Timer Event for FIQ */ +#define CNT_HP_IRQ_FIQ (1 << 6) +/* Virtual Timer Event for FIQ */ +#define CNT_V_IRQ_FIQ (1 << 7) + +#define ARM_LOCAL_IRQ_SOURCE0 (ARM_LOCAL_BASE + 0x60) +#define ARM_LOCAL_IRQ_SOURCE1 (ARM_LOCAL_BASE + 0x64) +#define ARM_LOCAL_IRQ_SOURCE2 (ARM_LOCAL_BASE + 0x68) +#define ARM_LOCAL_IRQ_SOURCE3 (ARM_LOCAL_BASE + 0x6c) +#define MAILBOX_IRQ_SHIFT 4 +#define CORE_IRQ (1 << 8) +#define PMU_IRQ (1 << 9) +#define AXI_QUIET (1 << 10) +#define TIMER_IRQ (1 << 11) +#define AXI_IRQ (1 << 30) + +#define ARM_LOCAL_FRQ_SOURCE0 (ARM_LOCAL_BASE + 0x70) +#define ARM_LOCAL_FRQ_SOURCE1 (ARM_LOCAL_BASE + 0x74) +#define ARM_LOCAL_FRQ_SOURCE2 (ARM_LOCAL_BASE + 0x78) +#define ARM_LOCAL_FRQ_SOURCE3 (ARM_LOCAL_BASE + 0x7c) diff --git a/mkrtos_knl/arch/aarch64/asm/base.h b/mkrtos_knl/arch/aarch64/asm/base.h new file mode 100755 index 000000000..f0c63d071 --- /dev/null +++ b/mkrtos_knl/arch/aarch64/asm/base.h @@ -0,0 +1,26 @@ +#pragma once + +#ifdef CONFIG_BOARD_PI3B +#define PBASE 0x3F000000 +#define ARM_LOCAL_BASE 0x40000000 +#define PBASE_END 0x41000000 +#else +/* Main peripherals on Low Peripheral mode + * - ARM and GPU can access + * see 1.2.4 + */ +#define PBASE 0x08000000 +#define PBASE_END 0x100000000 +/* + * ARM LOCAL register on Low Peripheral mode + * - Only ARM can access + * see 6.5.2 + */ +#define ARM_LOCAL_BASE 0xff800000 +#endif + +#define DEVICE_SIZE 0x2000000 +#define ARCH_PHYS_OFFSET 0 + +#define GIC_V2_DISTRIBUTOR_BASE (ARM_LOCAL_BASE + 0x00041000) +#define GIC_V2_CPU_INTERFIACE_BASE (ARM_LOCAL_BASE + 0x00042000) diff --git a/mkrtos_knl/arch/aarch64/asm/gpio.h b/mkrtos_knl/arch/aarch64/asm/gpio.h new file mode 100755 index 000000000..17c2e8cb6 --- /dev/null +++ b/mkrtos_knl/arch/aarch64/asm/gpio.h @@ -0,0 +1,13 @@ +#ifndef _P_GPIO_H +#define _P_GPIO_H + +#include "asm/base.h" + +#define GPFSEL1 (PBASE+0x00200004) +#define GPSET0 (PBASE+0x0020001C) +#define GPCLR0 (PBASE+0x00200028) +#define GPPUD (PBASE+0x00200094) +#define GPPUDCLK0 (PBASE+0x00200098) +#define GPIO_PUP_PDN_CNTRL_REG0 (PBASE+0x002000E4) + +#endif /*_P_GPIO_H */ diff --git a/mkrtos_knl/arch/aarch64/asm/io.h b/mkrtos_knl/arch/aarch64/asm/io.h new file mode 100755 index 000000000..37c31010a --- /dev/null +++ b/mkrtos_knl/arch/aarch64/asm/io.h @@ -0,0 +1,35 @@ + +#ifndef _P_IO_H +#define _P_BASE_H + +#if 1 +#define __arch_getl(a) (*(volatile unsigned int *)(a)) +#define __arch_putl(v,a) (*(volatile unsigned int *)(a) = (v)) + +#ifndef dmb +#define dmb() __asm__ __volatile__ ("" : : : "memory") +#endif +#define __iormb() dmb() +#define __iowmb() dmb() + +#define readl(c) ({ unsigned int __v = __arch_getl(c); __iormb(); __v; }) +#define writel(v,c) ({ unsigned int __v = v; __iowmb(); __arch_putl(__v,c);}) +#else +static inline void writel(unsigned int value, unsigned int addr) +{ + *(volatile unsigned int *)addr = value; +} + +static inline unsigned int readl(unsigned int addr) +{ + return *(volatile unsigned int *)addr; +} +#endif + +static inline void delay(unsigned int n) +{ + while(n--) + ; +} + +#endif diff --git a/mkrtos_knl/arch/aarch64/asm/irq.h b/mkrtos_knl/arch/aarch64/asm/irq.h new file mode 100755 index 000000000..4e0c80207 --- /dev/null +++ b/mkrtos_knl/arch/aarch64/asm/irq.h @@ -0,0 +1,26 @@ +#include "base.h" + +#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 SYSTEM_TIMER_IRQ_0 (1 << 0) +#define SYSTEM_TIMER_IRQ_1 (1 << 1) +#define SYSTEM_TIMER_IRQ_2 (1 << 2) +#define SYSTEM_TIMER_IRQ_3 (1 << 3) + +#define ARM_TIMER_IRQ (1 << 0) + +#define CORE0_INT_CTR (PERIPHERAL_BASE+0x40) +#define CORE0_INT_SOURCE (PERIPHERAL_BASE+0x60) +#define LOCAL_TIMER_INT (1 << 11) +#define CNTPNSIRQ_Int (1 << 1) + +void handle_timer_irq(void); diff --git a/mkrtos_knl/arch/aarch64/asm/mm.h b/mkrtos_knl/arch/aarch64/asm/mm.h new file mode 100755 index 000000000..5fdeb915c --- /dev/null +++ b/mkrtos_knl/arch/aarch64/asm/mm.h @@ -0,0 +1,13 @@ +#pragma once + +#define CONFIG_ARM64_VA_BITS 40 + +#define PAGE_SHIFT (CONFIG_PAGE_SHIFT) +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define VA_BITS (CONFIG_ARM64_VA_BITS) + +#ifndef __ASSEMBLER__ + +void memzero(unsigned long src, unsigned long n); + +#endif diff --git a/mkrtos_knl/arch/aarch64/asm/pl_uart.h b/mkrtos_knl/arch/aarch64/asm/pl_uart.h new file mode 100755 index 000000000..33a4d3256 --- /dev/null +++ b/mkrtos_knl/arch/aarch64/asm/pl_uart.h @@ -0,0 +1,16 @@ +#ifndef _P_UART_H +#define _P_UART_H + +#include "base.h" + +#define U_BASE (PBASE+0x00201000) + +#define U_DATA_REG (U_BASE) +#define U_FR_REG (U_BASE+0x18) +#define U_IBRD_REG (U_BASE+0x24) +#define U_FBRD_REG (U_BASE+0x28) +#define U_LCRH_REG (U_BASE+0x2C) +#define U_CR_REG (U_BASE+0x30) +#define U_IMSC_REG (U_BASE+0x38) + +#endif /*_P_UART_H */ diff --git a/mkrtos_knl/arch/aarch64/asm/sysregs.h b/mkrtos_knl/arch/aarch64/asm/sysregs.h new file mode 100755 index 000000000..c4bb4cb3e --- /dev/null +++ b/mkrtos_knl/arch/aarch64/asm/sysregs.h @@ -0,0 +1,200 @@ +#ifndef _SYSREGS_H +#define _SYSREGS_H + +#include "types_asm.h" + +/* + * SCTLR_EL1, System Control Register (EL1) + * AArch64-Reference-Manual v8.6, D13.2.113 + */ +/* Common SCTLR_ELx flags. */ +#define SCTLR_ELx_DSSBS (_BITUL(44)) +#define SCTLR_ELx_ENIA (_BITUL(31)) +#define SCTLR_ELx_ENIB (_BITUL(30)) +#define SCTLR_ELx_ENDA (_BITUL(27)) +#define SCTLR_ELx_EE (_BITUL(25)) +#define SCTLR_ELx_IESB (_BITUL(21)) +#define SCTLR_ELx_WXN (_BITUL(19)) +#define SCTLR_ELx_ENDB (_BITUL(13)) +#define SCTLR_ELx_I (_BITUL(12)) +#define SCTLR_ELx_SA (_BITUL(3)) +#define SCTLR_ELx_C (_BITUL(2)) +#define SCTLR_ELx_A (_BITUL(1)) +#define SCTLR_ELx_M (_BITUL(0)) + +#define SCTLR_ELx_FLAGS (SCTLR_ELx_M | SCTLR_ELx_A | SCTLR_ELx_C | \ + SCTLR_ELx_SA | SCTLR_ELx_I | SCTLR_ELx_IESB) + +/* SCTLR_EL2 specific flags. */ +#define SCTLR_EL2_RES1 \ + ((_BITUL(4)) | (_BITUL(5)) | (_BITUL(11)) | (_BITUL(16)) | \ + (_BITUL(18)) | (_BITUL(22)) | (_BITUL(23)) | (_BITUL(28)) | \ + (_BITUL(29))) +#define SCTLR_EL2_RES0 \ + ((_BITUL(6)) | (_BITUL(7)) | (_BITUL(8)) | (_BITUL(9)) | \ + (_BITUL(10)) | (_BITUL(13)) | (_BITUL(14)) | (_BITUL(15)) | \ + (_BITUL(17)) | (_BITUL(20)) | (_BITUL(24)) | (_BITUL(26)) | \ + (_BITUL(27)) | (_BITUL(30)) | (_BITUL(31)) | \ + (0xffffefffUL << 32)) + +#ifdef CONFIG_CPU_BIG_ENDIAN +#define ENDIAN_SET_EL2 SCTLR_ELx_EE +#define ENDIAN_CLEAR_EL2 0 +#else +#define ENDIAN_SET_EL2 0 +#define ENDIAN_CLEAR_EL2 SCTLR_ELx_EE +#endif + +/* SCTLR_EL2 value used for the hyp-stub */ +#define SCTLR_EL2_SET (SCTLR_ELx_IESB | ENDIAN_SET_EL2 | SCTLR_EL2_RES1) +#define SCTLR_EL2_CLEAR (SCTLR_ELx_M | SCTLR_ELx_A | SCTLR_ELx_C | \ + SCTLR_ELx_SA | SCTLR_ELx_I | SCTLR_ELx_WXN | \ + SCTLR_ELx_DSSBS | ENDIAN_CLEAR_EL2 | SCTLR_EL2_RES0) + +#define SCTLR_EL2_VALUE_MMU_DISABLED (SCTLR_EL2_RES1 | ENDIAN_SET_EL2) + +/* SCTLR_EL1 specific flags. */ +#define SCTLR_EL1_UCI (_BITUL(26)) +#define SCTLR_EL1_E0E (_BITUL(24)) +#define SCTLR_EL1_SPAN (_BITUL(23)) +#define SCTLR_EL1_NTWE (_BITUL(18)) +#define SCTLR_EL1_NTWI (_BITUL(16)) +#define SCTLR_EL1_UCT (_BITUL(15)) +#define SCTLR_EL1_DZE (_BITUL(14)) +#define SCTLR_EL1_UMA (_BITUL(9)) +#define SCTLR_EL1_SED (_BITUL(8)) +#define SCTLR_EL1_ITD (_BITUL(7)) +#define SCTLR_EL1_CP15BEN (_BITUL(5)) +#define SCTLR_EL1_SA0 (_BITUL(4)) + +#define SCTLR_EL1_RES1 \ + ((_BITUL(11)) | (_BITUL(20)) | (_BITUL(22)) | (_BITUL(28)) | \ + (_BITUL(29))) +#define SCTLR_EL1_RES0 \ + ((_BITUL(6)) | (_BITUL(10)) | (_BITUL(13)) | (_BITUL(17)) | \ + (_BITUL(27)) | (_BITUL(30)) | (_BITUL(31)) | \ + (0xffffefffUL << 32)) + +#ifdef CONFIG_CPU_BIG_ENDIAN +#define ENDIAN_SET_EL1 (SCTLR_EL1_E0E | SCTLR_ELx_EE) +#define ENDIAN_CLEAR_EL1 0 +#else +#define ENDIAN_SET_EL1 0 +#define ENDIAN_CLEAR_EL1 (SCTLR_EL1_E0E | SCTLR_ELx_EE) +#endif + +#define SCTLR_EL1_SET (SCTLR_ELx_M | SCTLR_ELx_C | SCTLR_ELx_SA |\ + SCTLR_EL1_SA0 | SCTLR_EL1_SED | SCTLR_ELx_I |\ + SCTLR_EL1_DZE | SCTLR_EL1_UCT |\ + SCTLR_EL1_NTWE | SCTLR_ELx_IESB | SCTLR_EL1_SPAN |\ + ENDIAN_SET_EL1 | SCTLR_EL1_UCI | SCTLR_EL1_RES1) +#define SCTLR_EL1_CLEAR (SCTLR_ELx_A | SCTLR_EL1_CP15BEN | SCTLR_EL1_ITD |\ + SCTLR_EL1_UMA | SCTLR_ELx_WXN | ENDIAN_CLEAR_EL1 |\ + SCTLR_ELx_DSSBS | SCTLR_EL1_NTWI | SCTLR_EL1_RES0) + +#define SCTLR_EL1_VALUE_MMU_DISABLED (SCTLR_EL1_RES1 | ENDIAN_SET_EL1) + +/* + * HCR_EL2, Hypervisor Configuration Register (EL2) + * AArch64-Reference-Manual v8.6, D13.2.47 + */ +#define HCR_FWB (UL(1) << 46) +#define HCR_API (UL(1) << 41) +#define HCR_APK (UL(1) << 40) +#define HCR_TEA (UL(1) << 37) +#define HCR_TERR (UL(1) << 36) +#define HCR_TLOR (UL(1) << 35) +#define HCR_E2H (UL(1) << 34) +#define HCR_ID (UL(1) << 33) +#define HCR_CD (UL(1) << 32) +#define HCR_RW_SHIFT 31 +#define HCR_RW (UL(1) << HCR_RW_SHIFT) +#define HCR_TRVM (UL(1) << 30) +#define HCR_HCD (UL(1) << 29) +#define HCR_TDZ (UL(1) << 28) +#define HCR_TGE (UL(1) << 27) +#define HCR_TVM (UL(1) << 26) +#define HCR_TTLB (UL(1) << 25) +#define HCR_TPU (UL(1) << 24) +#define HCR_TPC (UL(1) << 23) +#define HCR_TSW (UL(1) << 22) +#define HCR_TAC (UL(1) << 21) +#define HCR_TIDCP (UL(1) << 20) +#define HCR_TSC (UL(1) << 19) +#define HCR_TID3 (UL(1) << 18) +#define HCR_TID2 (UL(1) << 17) +#define HCR_TID1 (UL(1) << 16) +#define HCR_TID0 (UL(1) << 15) +#define HCR_TWE (UL(1) << 14) +#define HCR_TWI (UL(1) << 13) +#define HCR_DC (UL(1) << 12) +#define HCR_BSU (3 << 10) +#define HCR_BSU_IS (UL(1) << 10) +#define HCR_FB (UL(1) << 9) +#define HCR_VSE (UL(1) << 8) +#define HCR_VI (UL(1) << 7) +#define HCR_VF (UL(1) << 6) +#define HCR_AMO (UL(1) << 5) +#define HCR_IMO (UL(1) << 4) +#define HCR_FMO (UL(1) << 3) +#define HCR_PTW (UL(1) << 2) +#define HCR_SWIO (UL(1) << 1) +#define HCR_VM (UL(1) << 0) + +/* + * The bits we set in HCR: + * TLOR: Trap LORegion register accesses + * RW: 64bit by default, can be overridden for 32bit VMs + * TAC: Trap ACTLR + * TSC: Trap SMC + * TVM: Trap VM ops (until M+C set in SCTLR_EL1) + * TSW: Trap cache operations by set/way + * TWE: Trap WFE + * TWI: Trap WFI + * TIDCP: Trap L2CTLR/L2ECTLR + * BSU_IS: Upgrade barriers to the inner shareable domain + * FB: Force broadcast of all maintenance operations + * AMO: Override CPSR.A and enable signaling with VA + * IMO: Override CPSR.I and enable signaling with VI + * FMO: Override CPSR.F and enable signaling with VF + * SWIO: Turn set/way invalidates into set/way clean+invalidate + */ +#define HCR_GUEST_FLAGS (HCR_TSC | HCR_TSW | HCR_TWE | HCR_TWI | HCR_VM | \ + HCR_TVM | HCR_BSU_IS | HCR_FB | HCR_TAC | \ + HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW | HCR_TLOR | \ + HCR_FMO | HCR_IMO) +#define HCR_VIRT_EXCP_MASK (HCR_VSE | HCR_VI | HCR_VF) +#define HCR_HOST_NVHE_FLAGS (HCR_RW | HCR_API | HCR_APK | HCR_E2H) +#define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H) + +/* + * 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) +#define SCR_VALUE (\ + SCR_NS|SCR_RW|(1UL<<7)|(1UL<<8)\ +) +/* + * 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_EL2h (9 << 0) +#define SPSR_EL1 (SPSR_MASK_ALL | SPSR_EL1h) +#define SPSR_EL2 (SPSR_MASK_ALL | SPSR_EL2h) + +/* Current Exception Level values, as contained in CurrentEL */ +#define CurrentEL_EL1 (1 << 2) +#define CurrentEL_EL2 (2 << 2) +#define CurrentEL_EL3 (3 << 2) + + + + +#endif diff --git a/mkrtos_knl/arch/aarch64/asm/system.h b/mkrtos_knl/arch/aarch64/asm/system.h new file mode 100644 index 000000000..7f3e76918 --- /dev/null +++ b/mkrtos_knl/arch/aarch64/asm/system.h @@ -0,0 +1,30 @@ +#pragma once +#include +/* + * PSR bits + */ +#define PSR_MODE_EL0t 0x00000000 +#define PSR_MODE_EL1t 0x00000004 +#define PSR_MODE_EL1h 0x00000005 +#define PSR_MODE_EL2t 0x00000008 +#define PSR_MODE_EL2h 0x00000009 +#define PSR_MODE_EL3t 0x0000000c +#define PSR_MODE_EL3h 0x0000000d +#define PSR_MODE_MASK 0x0000000f + +typedef struct entry_frame { + struct { + mword_t regs[31]; + mword_t sp; + mword_t pc; + mword_t pstate; + }; + + mword_t orig_x0; + uint32_t syscallno; + uint32_t unused2; + + mword_t orig_addr_limit; + mword_t unused; + mword_t stackframe[2]; +} entry_frame_t; diff --git a/mkrtos_knl/arch/aarch64/asm/timer.h b/mkrtos_knl/arch/aarch64/asm/timer.h new file mode 100755 index 000000000..f253d5b7b --- /dev/null +++ b/mkrtos_knl/arch/aarch64/asm/timer.h @@ -0,0 +1,32 @@ +#include "base.h" + +/* System Timer on PI */ +#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) + +/* ARM side Timer on PI + * Reference: 12.2 Timer Registers + */ +#define ARM_TIMER_BASE (PBASE + 0xB000) +#define ARM_TIMER_LOAD (ARM_TIMER_BASE + 0x400) +#define ARM_TIMER_VALUE (ARM_TIMER_BASE + 0x404) +#define ARM_TIMER_CTRL (ARM_TIMER_BASE + 0x408) +#define ARM_TIMER_CLR (ARM_TIMER_BASE + 0x40c) + +#define CTRL_23BIT (1 << 1) // 23-bit counter +#define CTRL_INT_ENABLE (1 << 5) // Timer interrupt enabled +#define CTRL_ENABLE (1 << 7) // Timer enabled + +/* Local timer */ +#define TIMER_CTRL (PERIPHERAL_BASE+0x34) +#define TIMER_FLAG (PERIPHERAL_BASE+0x38) diff --git a/mkrtos_knl/arch/aarch64/asm/types_asm.h b/mkrtos_knl/arch/aarch64/asm/types_asm.h new file mode 100644 index 000000000..155bba29f --- /dev/null +++ b/mkrtos_knl/arch/aarch64/asm/types_asm.h @@ -0,0 +1,20 @@ + +#pragma once + +#ifdef __ASSEMBLY__ +#define _AC(X,Y) X +#define _AT(T,X) X +#else +#define __AC(X,Y) (X##Y) +#define _AC(X,Y) __AC(X,Y) +#define _AT(T,X) ((T)(X)) +#endif + +#define UL(x) (_UL(x)) +#define ULL(x) (_ULL(x)) + +#define _UL(x) (_AC(x, UL)) +#define _ULL(x) (_AC(x, ULL)) + +#define _BITUL(x) (_UL(1) << (x)) +#define _BITULL(x) (_ULL(1) << (x)) diff --git a/mkrtos_knl/arch/aarch64/asm_config.h b/mkrtos_knl/arch/aarch64/asm_config.h new file mode 100644 index 000000000..ac53f80ab --- /dev/null +++ b/mkrtos_knl/arch/aarch64/asm_config.h @@ -0,0 +1,14 @@ +#ifndef __ASM_CONFIG_H__ +#define __ASM_CONFIG_H__ + +#include "asm/mm.h" +#include "thread_arch.h" +#define SUPPORT_SMP CONFIG_SMP +#define SYS_CPU_NUM CONFIG_CPU //!< 系统cpu数量 + +#define MWORD_BYTES (sizeof(mword_t)) +#define MWORD_BITS (sizeof(mword_t) << 3UL) +#define MWORD_SHIFT (3) + +#define PT_REGS_SIZE 320 +#endif diff --git a/mkrtos_knl/arch/aarch64/asm_offset.h b/mkrtos_knl/arch/aarch64/asm_offset.h new file mode 100644 index 000000000..5a522bdee --- /dev/null +++ b/mkrtos_knl/arch/aarch64/asm_offset.h @@ -0,0 +1,42 @@ +#ifndef __ASM_OFFSETS_H__ +#define __ASM_OFFSETS_H__ +/* + * DO NOT MODIFY. + * + * This file was generated by Kbuild + */ + +#define S_FRAME_SIZE 320 /* sizeof(struct pt_regs) // */ +#define S_X0 0 /* offsetof(struct pt_regs, regs[0]) // */ +#define S_X1 8 /* offsetof(struct pt_regs, regs[1]) // */ +#define S_X2 16 /* offsetof(struct pt_regs, regs[2]) // */ +#define S_X3 24 /* offsetof(struct pt_regs, regs[3]) // */ +#define S_X4 32 /* offsetof(struct pt_regs, regs[4]) // */ +#define S_X5 40 /* offsetof(struct pt_regs, regs[5]) // */ +#define S_X6 48 /* offsetof(struct pt_regs, regs[6]) // */ +#define S_X7 56 /* offsetof(struct pt_regs, regs[7]) // */ +#define S_X8 64 /* offsetof(struct pt_regs, regs[8]) // */ +#define S_X10 80 /* offsetof(struct pt_regs, regs[10]) // */ +#define S_X12 96 /* offsetof(struct pt_regs, regs[12]) // */ +#define S_X14 112 /* offsetof(struct pt_regs, regs[14]) // */ +#define S_X16 128 /* offsetof(struct pt_regs, regs[16]) // */ +#define S_X18 144 /* offsetof(struct pt_regs, regs[18]) // */ +#define S_X20 160 /* offsetof(struct pt_regs, regs[20]) // */ +#define S_X22 176 /* offsetof(struct pt_regs, regs[22]) // */ +#define S_X24 192 /* offsetof(struct pt_regs, regs[24]) // */ +#define S_X26 208 /* offsetof(struct pt_regs, regs[26]) // */ +#define S_X28 224 /* offsetof(struct pt_regs, regs[28]) // */ +#define S_FP 232 /* offsetof(struct pt_regs, regs[29]) // */ +#define S_LR 240 /* offsetof(struct pt_regs, regs[30]) // */ +#define S_SP 248 /* offsetof(struct pt_regs, sp) // */ +#define S_PSTATE 264 /* offsetof(struct pt_regs, pstate) // */ +#define S_PC 256 /* offsetof(struct pt_regs, pc) // */ +// #define S_ORIG_X0 272 /* offsetof(struct pt_regs, orig_x0) // */ +// #define S_SYSCALLNO 280 /* offsetof(struct pt_regs, syscallno) // */ +// #define S_ORIG_ADDR_LIMIT 288 /* offsetof(struct pt_regs, orig_addr_limit) // */ +// #define S_STACKFRAME 304 /* offsetof(struct pt_regs, stackframe) // */ +// #define THREAD_CPU_CONTEXT 16 /* offsetof(struct task_struct, cpu_context) // */ +// #define TI_PREEMPT 148 /* offsetof(struct task_struct, preempt_count) // */ +// #define NEED_RESCHED 144 /* offsetof(struct task_struct, need_resched) // */ + +#endif diff --git a/mkrtos_knl/arch/aarch64/atomics.c b/mkrtos_knl/arch/aarch64/atomics.c new file mode 100644 index 000000000..838857440 --- /dev/null +++ b/mkrtos_knl/arch/aarch64/atomics.c @@ -0,0 +1,123 @@ + +#include +#include + +bool_t atomic_cmpxchg(umword_t *v, umword_t old, umword_t new) +{ + umword_t oldval, res; + + asm volatile( + "1:\n" + "ldxr %1, %2\n" + "eor %0, %1, %3\n" + "cbnz %0, 2f\n" + "stxr %w0, %4, %2\n" + "cbnz %w0, 1b\n" + "2:" + : "=&r"(res), "=&r"(oldval), "+Q"(*v) + : "r"(old), "r"(new) + : "cc"); + return !res; +} +void atomic_and(umword_t *l, umword_t val) +{ + umword_t tmp, ret; + + asm volatile( + "1:\n" + "ldxr %0, %2\n" + "and %0, %0, %3\n" + "stxr %w1, %0, %2\n" + "cbnz %w1, 1b\n" + : "=&r"(tmp), "=&r"(ret), "+Q"(*l) + : "r"(val) + : "cc"); +} +umword_t atomic_and_return(umword_t *l, umword_t val) +{ + umword_t tmp, ret; + + asm volatile( + "ldxr %0, %2\n" + "and %1, %0, %3\n" + : "=&r"(tmp), "=&r"(ret), "+Q"(*l) + : "r"(val) + : "cc"); + return !!ret; +} +void atomic_or(umword_t *l, umword_t val) +{ + umword_t tmp, ret; + + asm volatile( + "1:\n" + "ldxr %0, %2\n" + "orr %0, %0, %3\n" + "stxr %w1, %0, %2\n" + "cbnz %w1, 1b\n" + : "=&r"(tmp), "=&r"(ret), "+Q"(*l) + : "r"(val) + : "cc"); +} +umword_t atomic_sub_return(umword_t i, atomic64_t *v) +{ + umword_t tmp; + umword_t ret; + + asm volatile( + "1:\n" + "ldxr %0, %2\n" + "sub %0, %0, %3\n" + "stxr %w1, %0, %2\n" + "cbnz %w1, 1b\n" + : "=&r"(ret), "=&r"(tmp), "+Q"(v->counter) + : "r"(i)); + return ret; +} +umword_t atomic_add_return(umword_t i, atomic64_t *v) +{ + umword_t tmp; + umword_t ret; + + asm volatile( + "1:\n" + "ldxr %0, %2\n" + "add %0, %0, %3\n" + "stxr %w1, %0, %2\n" + "cbnz %w1, 1b\n" + : "=&r"(ret), "=&r"(tmp), "+Q"(v->counter) + : "r"(i)); + return ret; +} +umword_t atomic_fetch_and(umword_t i, atomic64_t *v) +{ + umword_t tmp, ret; + umword_t old; + + asm volatile( + "1:\n" + "ldxr %2, %3\n" + "and %0, %2, %4\n" + "stxr %w1, %0, %3\n" + "cbnz %w1, 1b\n" + : "=&r"(tmp), "=&r"(ret), "=&r"(old), "+Q"(v->counter) + : "r"(i) + : "cc"); + return old; +} +umword_t atomic_fetch_or(umword_t i, atomic64_t *v) +{ + umword_t tmp, ret; + umword_t old; + + asm volatile( + "1:\n" + "ldxr %2, %3\n" + "orr %0, %2, %4\n" + "stxr %w1, %0, %3\n" + "cbnz %w1, 1b\n" + : "=&r"(tmp), "=&r"(ret), "=&r"(old), "+Q"(v->counter) + : "r"(i) + : "cc"); + return old; +} diff --git a/mkrtos_knl/arch/aarch64/atomics.h b/mkrtos_knl/arch/aarch64/atomics.h new file mode 100644 index 000000000..d7c6792c5 --- /dev/null +++ b/mkrtos_knl/arch/aarch64/atomics.h @@ -0,0 +1,68 @@ +#pragma once +#include +typedef struct atomic64 +{ + umword_t counter; +} atomic64_t; + +typedef atomic64_t atomic_t; +#define ATOMIC64_INIT(i) ((atomic64_t){(i)}) + +#define atomic_read(v) (*(volatile umword_t *)(&(v)->counter)) +#define atomic_set(v, i) (((v)->counter) = i) + +bool_t atomic_cmpxchg(umword_t *v, umword_t old, umword_t new); +void atomic_and(umword_t *l, umword_t val); +umword_t atomic_and_return(umword_t *l, umword_t val); +void atomic_or(umword_t *l, umword_t val); +umword_t atomic_sub_return(umword_t i, atomic64_t *v); +umword_t atomic_add_return(umword_t i, atomic64_t *v); +umword_t atomic_fetch_and(umword_t i, atomic64_t *v); +umword_t atomic_fetch_or(umword_t i, atomic64_t *v); + +static inline void atomic_add(umword_t i, atomic64_t *v) +{ + atomic_add_return(i, v); +} +static inline void atomic_sub(umword_t i, atomic64_t *v) +{ + atomic_sub_return(i, v); +} +static inline void atomic_inc(atomic64_t *v) +{ + atomic_add_return(1, v); +} +static inline void atomic_dec(atomic64_t *v) +{ + atomic_sub_return(1, v); +} +static inline umword_t atomic_inc_return(atomic64_t *v) +{ + return atomic_add_return(1, v); +} +static inline umword_t atomic_dec_return(atomic64_t *v) +{ + return atomic_sub_return(1, v); +} + +static inline umword_t atomic_add_and_test(umword_t i, atomic64_t *v) +{ + return atomic_add_return(i, v) == 0; +} + +static inline umword_t atomic_sub_and_test(umword_t i, atomic64_t *v) +{ + return atomic_sub_return(i, v) == 0; +} +static inline umword_t atomic_inc_and_test(atomic64_t *v) +{ + return atomic_inc_return(v) == 0; +} +static inline umword_t atomic_dec_and_test(atomic64_t *v) +{ + return atomic_dec_return(v) == 0; +} +static inline umword_t atomic_add_negative(umword_t i, atomic64_t *v) +{ + return (umword_t)atomic_add_return(i, v) < 0; +} diff --git a/mkrtos_knl/arch/aarch64/complier.h b/mkrtos_knl/arch/aarch64/complier.h new file mode 100644 index 000000000..6261bea5a --- /dev/null +++ b/mkrtos_knl/arch/aarch64/complier.h @@ -0,0 +1,6 @@ +#pragma once + +#define tostring(s...) #s + +#define BEGIN_FUNC(_name) .global _name ; .type _name, %function ; _name: +#define END_FUNC(_name) .size _name, .-_name diff --git a/mkrtos_knl/arch/aarch64/dummy.c b/mkrtos_knl/arch/aarch64/dummy.c new file mode 100644 index 000000000..e69de29bb diff --git a/mkrtos_knl/arch/aarch64/early_boot.c b/mkrtos_knl/arch/aarch64/early_boot.c new file mode 100644 index 000000000..5f83a296a --- /dev/null +++ b/mkrtos_knl/arch/aarch64/early_boot.c @@ -0,0 +1,206 @@ + +#include +#include "early_boot.h" +#include "asm/sysregs.h" +#include "asm/base.h" +#include "asm/mm.h" +#include +#include +#include "pager.h" +#include +#include +#include + +#define DATA_BOOT_SECTION ".data.boot" +#define TEXT_BOOT_SECTION ".text.boot" + +#define TCR_DEFAULT (((1UL) << 31) | (1UL << 23) | \ + (3UL << 12) | (1UL << 10) | (1UL << 8) | ((64UL - CONFIG_ARM64_VA_BITS))) + +extern char _text_boot[]; +extern char _etext_boot[]; +extern char _data_boot[]; +extern char _edata_boot[]; +extern char _ebss[]; +extern char _text[]; +extern char _buddy_data_start[]; +extern char _buddy_data_end[]; + +#define BOOT_PAGER_NR 128 +// __ALIGN__(THREAD_BLOCK_SIZE) SECTION(DATA_BOOT_SECTION) uint8_t boot_stack[THREAD_BLOCK_SIZE] = {0}; +static SECTION(DATA_BOOT_SECTION) __ALIGN__(PAGE_SIZE) uint8_t pages[BOOT_PAGER_NR * SYS_CPU_NUM][PAGE_SIZE]; +static SECTION(DATA_BOOT_SECTION) uint8_t pages_used[BOOT_PAGER_NR * SYS_CPU_NUM]; +static SECTION(TEXT_BOOT_SECTION) inline int boot_get_current_cpu_id(void) +{ + return read_sysreg(mpidr_el1) & 0XFFUL; +} +static SECTION(TEXT_BOOT_SECTION) void *page_alloc(void) +{ + for (int i = 0; i < BOOT_PAGER_NR * SYS_CPU_NUM; i++) + { + if (pages_used[i + boot_get_current_cpu_id() * BOOT_PAGER_NR] == 0) + { + pages_used[i + boot_get_current_cpu_id() * BOOT_PAGER_NR] = 1; + return (void *)pages[i + boot_get_current_cpu_id() * BOOT_PAGER_NR]; + } + } + return NULL; +} +static SECTION(TEXT_BOOT_SECTION) void page_free(void *mem) +{ + for (int i = 0; i < BOOT_PAGER_NR * SYS_CPU_NUM; i++) + { + if (pages_used[i + arch_get_current_cpu_id() * BOOT_PAGER_NR] == 1 && pages[i + arch_get_current_cpu_id() * BOOT_PAGER_NR] == mem) + { + pages_used[i + arch_get_current_cpu_id() * BOOT_PAGER_NR] = 0; + break; + } + } +} + +static SECTION(TEXT_BOOT_SECTION) void *boot_memset(void *dst, int s, size_t count) +{ + register char *a = dst; + count++; /* this actually creates smaller code than using count-- */ + while (--count) + *a++ = s; + return dst; +} + +#define PTE_TYPE_BLOCK 0x0UL +#define PTE_TYPE_TAB 0x3UL + +static SECTION(DATA_BOOT_SECTION) pte_t boot_kpdir[PAGE_SIZE / MWORD_BYTES]; +SECTION(DATA_BOOT_SECTION) +static page_entry_t kpdir = { + .dir = boot_kpdir, + .depth = PAGE_DEEP, + .lv_shift_sizes[0] = 39, + .lv_shift_sizes[1] = 30, + .lv_shift_sizes[2] = 21, + .lv_shift_sizes[3] = 12}; + +void knl_pdir_init(page_entry_t *pdir, pte_t *dir, int page_deep) +{ + pdir->dir = dir; + pdir->depth = page_deep; + pdir->lv_shift_sizes[0] = 39; + pdir->lv_shift_sizes[1] = 30; + pdir->lv_shift_sizes[2] = 21; + pdir->lv_shift_sizes[3] = 12; +} + +SECTION(TEXT_BOOT_SECTION) +pte_t *pages_walk(page_entry_t *pdir, addr_t virt_addr, mword_t size, void *(*fn_alloc)(void)) +{ + int i; + pte_t *next = &pdir->dir[(virt_addr >> pdir->lv_shift_sizes[(PAGE_DEEP - pdir->depth)]) & 0x1ffUL]; + + for (i = (PAGE_DEEP - pdir->depth); i < PAGE_DEEP; i++) + { + if (pdir->lv_shift_sizes[i] == size) + { + break; + } + } + assert(i != PAGE_DEEP); + + for (int j = (PAGE_DEEP - pdir->depth); j < PAGE_DEEP; j++) + { + if (j == i) + { + return next; + } + if (next->pte == 0) + { + next->pte = (mword_t)fn_alloc(); + assert(next->pte); + next->pte |= 3UL; + _dmb(ishst); + } + assert((j + 1) < PAGE_DEEP); + next = &((pte_t *)(next->pte & ~3UL))[(virt_addr >> pdir->lv_shift_sizes[j + 1]) & 0x1ffUL]; + } + assert(0); +} +SECTION(TEXT_BOOT_SECTION) +void map_mm(page_entry_t *pdir, addr_t virt_addr, addr_t phys_addr, + mword_t page_order, mword_t pfn_cn, mword_t attr) +{ + for (mword_t i = 0; i < pfn_cn; i++) + { + pte_t *pte = pages_walk(pdir, virt_addr + (i << page_order), page_order, page_alloc); + + assert(pte); + pte->pte = (phys_addr + (i << page_order)) | attr; + _dmb(ishst); + } +} + +static SECTION(TEXT_BOOT_SECTION) void boot_init_pageing(page_entry_t *kpdir, bool_t init_pages) +{ + uint64_t parang; + uint64_t tmp; + + write_sysreg(0x00ff4400, mair_el2); + if (init_pages) + { + map_mm(kpdir, 0x40000000, 0x40000000, 30, 1, 0x709); + // map_mm(kpdir, _text_boot, _text_boot, PAGE_SHIFT, ALIGN(_edata_boot - _text_boot, PAGE_SIZE) >> PAGE_SHIFT, 0x70b); + // map_mm(kpdir, _text, _edata_boot, PAGE_SHIFT, ALIGN(_buddy_data_end - _text, PAGE_SIZE) >> PAGE_SHIFT, 0x70b); + map_mm(kpdir, PBASE, PBASE, 21, DEVICE_SIZE >> 21, 0x709); + } + tmp = read_sysreg(ID_AA64MMFR0_EL1); + parang = tmp & 0xf; + if (parang > ID_AA64MMFR0_PARANGE_48) + { + parang = ID_AA64MMFR0_PARANGE_48; + } + write_sysreg(TCR_DEFAULT | (parang << 16UL), tcr_el2); + _dsb(sy); + write_sysreg(kpdir->dir, ttbr0_el2); +} + +SECTION(TEXT_BOOT_SECTION) +int boot_enable_mmu(void) +{ + mword_t tmp; + + _dsb(ish); + asm volatile("tlbi alle2is"); + asm volatile("tlbi vmalle1is"); + _dsb(ish); + // write_sysreg(SCTLR_ELx_M, sctlr_el2); + write_sysreg(0x30c51835, sctlr_el2); + _isb(); + asm volatile("ic iallu"); + _dsb(nsh); + _isb(); + return 0; +} + +SECTION(TEXT_BOOT_SECTION) +page_entry_t *boot_get_pdir(void) +{ + return &kpdir; +} + +SECTION(TEXT_BOOT_SECTION) +void per_cpu_boot_mapping(bool_t init_pages) +{ + boot_init_pageing(&kpdir, init_pages); + _dsb(ish); + asm volatile("ic iallu"); + boot_enable_mmu(); +} +extern void jump_kenel_main(void); + +// 启动的恒等映射 +SECTION(TEXT_BOOT_SECTION) +void boot_mapping(void) +{ + boot_memset(pages, 0, sizeof(pages)); + boot_memset(pages_used, 0, sizeof(pages_used)); + per_cpu_boot_mapping(TRUE); + jump_kenel_main(); +} diff --git a/mkrtos_knl/arch/aarch64/early_boot.h b/mkrtos_knl/arch/aarch64/early_boot.h new file mode 100644 index 000000000..3c19e09ee --- /dev/null +++ b/mkrtos_knl/arch/aarch64/early_boot.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include "pager.h" +#include "asm/mm.h" +#include "asm_config.h" + +#define PAGE_DEEP 4 + +typedef struct page_entry +{ + pte_t *dir; //!< 存储页表地址 + uint8_t lv_shift_sizes[PAGE_DEEP]; //!< 页表翻译的大小,order + uint8_t depth; //!< 页表深度 +} page_entry_t; + +pte_t *pages_walk(page_entry_t *pdir, addr_t virt_addr, mword_t size, void *(*fn_alloc)(void)); +void map_mm(page_entry_t *pdir, addr_t virt_addr, addr_t phys_addr, + mword_t page_order, mword_t pfn_cn, mword_t attr); +void per_cpu_boot_mapping(bool_t init_pages); +page_entry_t *boot_get_pdir(void); +void knl_pdir_init(page_entry_t *pdir, pte_t *dir, int page_deep); diff --git a/mkrtos_knl/arch/aarch64/exception.c b/mkrtos_knl/arch/aarch64/exception.c new file mode 100644 index 000000000..4ab7a4811 --- /dev/null +++ b/mkrtos_knl/arch/aarch64/exception.c @@ -0,0 +1,25 @@ +#include +#include +static const char *const bad_mode_handler[] = { + "Sync Abort", + "IRQ", + "FIQ", + "SError"}; + +void bad_mode(struct pt_regs *regs, int reason, unsigned int esr) +{ + printk("Bad mode for %s handler detected, esr=0x%x ec=0x%x far_el2=0x%lx\n", + bad_mode_handler[reason], esr, esr >> 26, read_sysreg(far_el2)); + + mword_t x29; + + asm volatile("mov %0, x29" : "=r"(x29)); + printk("x29 %lx.\n", x29); + for (size_t i = 0; i < 5; i++) + { + x29 = *(long *)(x29); + printk("kernel sync instruction addr is %lx\n", *(long *)(x29 + 8)); + } + while (1) + ; +} diff --git a/mkrtos_knl/arch/aarch64/hyp.c b/mkrtos_knl/arch/aarch64/hyp.c new file mode 100644 index 000000000..27e2b21c7 --- /dev/null +++ b/mkrtos_knl/arch/aarch64/hyp.c @@ -0,0 +1,151 @@ +#include +enum Scr_bits +{ + Scr_ns = 1UL << 0, ///< Non-Secure mode + Scr_irq = 1UL << 1, ///< IRQ to EL3 + Scr_fiq = 1UL << 2, ///< FIQ to EL3 + Scr_ea = 1UL << 3, ///< External Abort and SError to EL3 + Scr_smd = 1UL << 7, ///< SMC disable + Scr_hce = 1UL << 8, ///< HVC enable at EL1, EL2, and EL3 + Scr_sif = 1UL << 9, ///< Secure instruction fetch enable + Scr_rw = 1UL << 10, ///< EL2 / EL1 is AArch64 + Scr_st = 1UL << 11, ///< Trap Secure EL1 access to timer to EL3 + Scr_twi = 1UL << 12, ///< Trap WFI to EL3 + Scr_twe = 1UL << 13, ///< Trap WFE to EL3 + Scr_apk = 1UL << 16, ///< Do not trap on Pointer Authentication key accesses + Scr_api = 1UL << 17, ///< Do not trap on Pointer Authentication instructions + Scr_eel2 = 1UL << 18, ///< Secure EL2 enable +}; + +enum +{ + Sctlr_m = 1UL << 0, + Sctlr_a = 1UL << 1, + Sctlr_c = 1UL << 2, + Sctlr_sa = 1UL << 3, + Sctlr_sa0 = 1UL << 4, + Sctlr_cp15ben = 1UL << 5, + Sctlr_itd = 1UL << 7, + Sctlr_sed = 1UL << 8, + Sctlr_uma = 1UL << 9, + Sctlr_i = 1UL << 12, + Sctlr_dze = 1UL << 14, + Sctlr_uct = 1UL << 15, + Sctlr_ntwi = 1UL << 16, + Sctlr_ntwe = 1UL << 18, + Sctlr_wxn = 1UL << 19, + Sctlr_e0e = 1UL << 24, + Sctlr_ee = 1UL << 25, + Sctlr_uci = 1UL << 26, + + Sctlr_el1_res = (1UL << 11) | (1UL << 20) | (3UL << 22) | (3UL << 28), + + Sctlr_el1_generic = Sctlr_c | Sctlr_cp15ben | Sctlr_i | Sctlr_dze | Sctlr_uct | Sctlr_uci | Sctlr_el1_res, +}; +enum +{ + Scr_default_bits = Scr_ns | Scr_rw | Scr_smd | Scr_hce, +}; + +enum +{ + Hcr_vm = 1UL << 0, ///< Virtualization enable + Hcr_swio = 1UL << 1, ///< Set/way invalidation override + Hcr_ptw = 1UL << 2, ///< Protected table walk + Hcr_fmo = 1UL << 3, ///< Physical FIQ routing + Hcr_imo = 1UL << 4, ///< Physical IRQ routing + Hcr_amo = 1UL << 5, ///< Physical SError interrupt routing + Hcr_dc = 1UL << 12, ///< Default cacheability + Hcr_tid2 = 1UL << 17, ///< Trap CTR, CESSLR, etc. + Hcr_tid3 = 1UL << 18, ///< Trap ID, etc. + Hcr_tsc = 1UL << 19, ///< Trap SMC instructions + Hcr_tidcp = 1UL << 20, ///< Trap implementation defined functionality + Hcr_tactlr = 1UL << 21, ///< Trap ACTLR, etc. + Hcr_tsw = 1UL << 22, ///< Trap cache maintenance instructions + Hcr_ttlb = 1UL << 25, ///< Trap TLB maintenance instructions + Hcr_tvm = 1UL << 26, ///< Trap virtual memory controls + Hcr_tge = 1UL << 27, ///< Trap General Exceptions + Hcr_hcd = 1UL << 29, ///< HVC instruction disable + Hcr_trvm = 1UL << 30, ///< Trap reads of virtual memory controls + Hcr_rw = 1UL << 31, ///< EL1 is AArch64 +}; + +enum +{ + Hcr_must_set_bits = Hcr_vm | Hcr_swio | Hcr_ptw | Hcr_amo | Hcr_imo | Hcr_fmo | Hcr_tidcp | Hcr_tsc | Hcr_tactlr, + + /** + * HCR value to be used for the VMM. + * + * The AArch64 VMM is currently running in EL1. + */ + Hcr_host_bits = Hcr_must_set_bits | Hcr_rw | Hcr_dc, + + /** + * HCR value to be used for normal threads. + * + * On AArch64 (with virtualization support) running in EL1. + */ + Hcr_non_vm_bits = Hcr_must_set_bits | Hcr_rw | Hcr_dc | Hcr_tsw | Hcr_ttlb | Hcr_tvm | Hcr_trvm +}; + +enum +{ + Mdcr_hpmn_mask = 0xf, + Mdcr_tpmcr = 1UL << 5, + Mdcr_tpm = 1UL << 6, + Mdcr_hpme = 1UL << 7, + Mdcr_tde = 1UL << 8, + Mdcr_tda = 1UL << 9, + Mdcr_tdosa = 1UL << 10, + Mdcr_tdra = 1UL << 11, + + Mdcr_bits = Mdcr_tpmcr | Mdcr_tpm | Mdcr_tda | Mdcr_tdosa | Mdcr_tdra, + Mdcr_vm_mask = 0xf00, +}; +enum +{ + /// Attributes for page-table walks + Tcr_attribs = (3UL << 4) // SH0 + | (1UL << 2) // ORGN0 + | (1UL << 0), // IRGN0 + + /** + * Memory Attribute Indirection (MAIR0) + * Attr0: Device-nGnRnE memory + * Attr1: Normal memory, Inner/Outer Non-cacheable + * Attr2: Normal memory, RW, Inner/Outer Write-Back Cacheable (Non-transient) + */ + Mair0_prrr_bits = 0x00ff4400, + Mair1_nmrr_bits = 0, +}; +enum +{ + Vtcr_bits = (1UL << 6) // SL0 + | (2UL << 16) // PS + | (25UL << 0) // T0SZ +}; +enum Hstr_values +{ + Hstr_non_vm = 0x9f6f, // ALL but crn=13,7 (TPIDxxR, DSB) CP15 traped + Hstr_vm = 0x0, // none +}; +void init_arm_hyp(void) +{ + // asm volatile ("msr VBAR_EL2, %x0" : : "r"(&exception_vector)); + asm volatile("msr VTCR_EL2, %x0" : : "r"((1UL << 31) // RES1 + | (Tcr_attribs << 8) | Vtcr_bits)); + + asm volatile("msr MDCR_EL2, %x0" : : "r"((mword_t)Mdcr_bits)); + + asm volatile("msr SCTLR_EL1, %x0" : : "r"((mword_t)Sctlr_el1_generic)); + asm volatile("msr HCR_EL2, %x0" : : "r"(Hcr_non_vm_bits)); + asm volatile("msr HSTR_EL2, %x0" : : "r"(Hstr_non_vm)); + + _dsb(sy); + _isb(); + + // HCPTR + asm volatile("msr CPTR_EL2, %x0" : : "r"(0x33ffUL // TCP: 0-9, 12-13 + | (1 << 20))); // TTA +} \ No newline at end of file diff --git a/mkrtos_knl/arch/aarch64/hyp.h b/mkrtos_knl/arch/aarch64/hyp.h new file mode 100644 index 000000000..2f5afb990 --- /dev/null +++ b/mkrtos_knl/arch/aarch64/hyp.h @@ -0,0 +1,3 @@ +#pragma once + +void init_arm_hyp(void); diff --git a/mkrtos_knl/arch/aarch64/link.lds b/mkrtos_knl/arch/aarch64/link.lds new file mode 100644 index 000000000..b708ffa3b --- /dev/null +++ b/mkrtos_knl/arch/aarch64/link.lds @@ -0,0 +1,85 @@ +ENTRY(_start); +SECTIONS +{ + . = 0x40000000+0x1000; + kernel_start = .; + _text_boot = .; + .text.boot : + { + *(.text.boot) + } + . = ALIGN(4096); + _etext_boot = .; + _data_boot = .; + .data.boot : + { + *(.data.boot) + } + . = ALIGN(4096); + _edata_boot = .; + . = _edata_boot; + _text = .; + .text : + { + *(.text) + . = ALIGN(8); + _mkrtos_init_start = .; + KEEP (*(SORT(.mkrtos.init.*))) + _mkrtos_init_end = .; + } + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } + . = ALIGN(4096); + _etext = .; + _rodata = .; + .rodata : + { + *(.rodata) + } + _erodata = .; + _data = .; + .data : + { + *(.data) + . = ALIGN(0x8); + _pre_cpu_data_start = .; + KEEP (*(.data.per_cpu)) + _pre_cpu_data_end = .; + } + _edata = .; + . = ALIGN(0x8); + _bss = .; + bss_begin = .; + .bss : + { + *(.bss*) + } + bss_end = .; + _ebss = .; + . = ALIGN(4096); + _buddy_data_start = .; + .buddy : + { + *(.buddy*) + . += 0x1000000; + } + _buddy_data_end = .; +} diff --git a/mkrtos_knl/arch/aarch64/link.lds.S b/mkrtos_knl/arch/aarch64/link.lds.S new file mode 100644 index 000000000..bbcb5577c --- /dev/null +++ b/mkrtos_knl/arch/aarch64/link.lds.S @@ -0,0 +1,121 @@ +ENTRY(_start); + +SECTIONS +{ + /* + * 设置mkrtos的加载入口地址为0x80000 + * + * 这里“.”表示location counter,当前位置 + */ + . = 0x40000000+0x1000; + kernel_start = .; + /* + * 这里是第一个段text.boot,起始地址就是0x80000 + * 这个段存放了benos的第一条指令 + */ + _text_boot = .; + .text.boot : + { + *(.text.boot) + } + . = ALIGN(4096); + _etext_boot = .; + + _data_boot = .; + .data.boot : + { + *(.data.boot) + } + . = ALIGN(4096); + _edata_boot = .; + + . = _edata_boot; + /* + * text代码段 + */ + _text = .; + .text : + { + *(.text) + . = ALIGN(8); + _mkrtos_init_start = .; + KEEP (*(SORT(.mkrtos.init.*))) + _mkrtos_init_end = .; + } + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } + . = ALIGN(4096); + _etext = .; + + /* + * 只读数据段 + */ + + _rodata = .; + .rodata : + { + *(.rodata) + } + _erodata = .; + + + /* + * 数据段 + */ + _data = .; + .data : + { + *(.data) + + . = ALIGN(0x8); + _pre_cpu_data_start = .; + KEEP (*(.data.per_cpu)) + _pre_cpu_data_end = .; + } + _edata = .; + + /* + * bss段 + * + * ALIGN(8)表示8个字节对齐 + * bss_begin的起始地址以8字节对齐 + */ + . = ALIGN(0x8); + _bss = .; + bss_begin = .; + .bss : + { + *(.bss*) + } + bss_end = .; + _ebss = .; + + . = ALIGN(4096); + _buddy_data_start = .; + .buddy : + { + *(.buddy*) + . += 0x1000000; + } + _buddy_data_end = .; + + +} diff --git a/mkrtos_knl/arch/aarch64/pager.c b/mkrtos_knl/arch/aarch64/pager.c new file mode 100644 index 000000000..dac1d5278 --- /dev/null +++ b/mkrtos_knl/arch/aarch64/pager.c @@ -0,0 +1,65 @@ + +#include +// #include +#include "asm/sysregs.h" +#include +#include "asm/base.h" +#include "pager.h" +#include "asm/mm.h" +#include +static inline mword_t pgd_offset(addr_t virt) +{ + return (((virt) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)); +} +static inline mword_t pmd_offset(addr_t virt) +{ + return (((virt) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)); +} +static inline mword_t pud_offset(addr_t virt) +{ + return (((virt) >> PUD_SHIFT) & (PTRS_PER_PUD - 1)); +} +static inline mword_t pte_offset(addr_t virt) +{ + return (((virt) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)); +} + +static void pte_print(pgd_t *pgdp) +{ + for (size_t i = 0; i < PAGE_SIZE / sizeof(void *); i++) + { + if (PTE_GET_VALID(pgdp[i].pgd)) + { + printk("%d pgd 0x%lx, next pg 0x%lx\n", i, pgdp[i].pgd, PTE_ADDR(pgdp[i].pgd, PAGE_SHIFT)); + for (size_t j = 0; j < PAGE_SIZE / sizeof(void *); j++) + { + pud_t *pudp = &((pud_t *)(PTE_ADDR(pgdp[i].pgd, PAGE_SHIFT)))[j]; + if (PTE_GET_VALID(pudp->pud)) + { + printk(" %d pud 0x%lx, next pg 0x%lx\n", j, pudp->pud, PTE_ADDR(pudp->pud, PAGE_SHIFT)); + for (size_t m = 0; m < PAGE_SIZE / sizeof(void *); m++) + { + pmd_t *pmdp = &((pmd_t *)(PTE_ADDR(pudp->pud, PAGE_SHIFT)))[m]; + if (PTE_GET_VALID(pmdp->pmd) && (pmdp->pmd & 0x2)) + { + printk(" %d pmd 0x%lx, next pg 0x%lx\n", m, pmdp->pmd, PTE_ADDR(pmdp->pmd, PAGE_SHIFT)); + + for (size_t n = 0; n < PAGE_SIZE / sizeof(void *); n++) + { + pte_t *ptep = &((pte_t *)(PTE_ADDR(pmdp->pmd, PAGE_SHIFT)))[n]; + if (PTE_GET_VALID(ptep->pte)) + { + printk(" %d pte 0x%lx, next pg 0x%lx\n", n, ptep->pte, PTE_ADDR(ptep->pte, PAGE_SHIFT)); + } + } + } + else if (PTE_GET_VALID(pmdp->pmd)) + { + printk(" %d pmd 0x%lx, addr 0x%lx\n", m, pmdp->pmd, PTE_ADDR(pmdp->pmd, PAGE_SHIFT)); + } + } + } + } + } + } +} diff --git a/mkrtos_knl/arch/aarch64/pager.h b/mkrtos_knl/arch/aarch64/pager.h new file mode 100644 index 000000000..9e1883401 --- /dev/null +++ b/mkrtos_knl/arch/aarch64/pager.h @@ -0,0 +1,257 @@ +#pragma once + +#include +#include +typedef struct pgd +{ + mword_t pgd; +} pgd_t; + +typedef struct pud +{ + mword_t pud; +} pud_t; + +typedef struct pmd +{ + mword_t pmd; +} pmd_t; + +typedef struct pte +{ + mword_t pte; +} pte_t; + +#define PTE_GET_VALID(p) (p & 0x1UL) +#define PTE_GET_TYPE(p) (p & 0x2UL) + +#define PTE_LOW_ATTR(p) (MASK_LSB(p, 2) & 0x3ffUL) +#define PTE_HIGH_ATTR(p) (MASK_LSB(p, 52) >> 52UL) + +#define PTE_ADDR(p, n) (MASK_LSB(p, n)) +#define PTE_PA(p, n) PTE_ADDR(p, n) +#define PTE_NEXT_BASE_ADDR(p, n) PTE_ADDR(p, n) + +#define PTE_PA_4K(p) PTE_ADDR(p, 12) + +/* PGD */ +#define PGDIR_SHIFT 39 +#define PGDIR_SIZE (1UL << PGDIR_SHIFT) +#define PGDIR_MASK (~(PGDIR_SIZE - 1)) +#define PTRS_PER_PGD (1 << (VA_BITS - PGDIR_SHIFT)) + +/* PUD */ +#define PUD_SHIFT 30 +#define PUD_SIZE (1UL << PUD_SHIFT) +#define PUD_MASK (~(PUD_SIZE - 1)) +#define PTRS_PER_PUD (1 << (PGDIR_SHIFT - PUD_SHIFT)) + +/* PMD */ +#define PMD_SHIFT 21 +#define PMD_SIZE (1UL << PMD_SHIFT) +#define PMD_MASK (~(PMD_SIZE - 1)) +#define PTRS_PER_PMD (1 << (PUD_SHIFT - PMD_SHIFT)) + +/* PTE */ +#define PTE_SHIFT 12 +#define PTE_SIZE (1UL << PTE_SHIFT) +#define PTE_MASK (~(PTE_SIZE - 1)) +#define PTRS_PER_PTE (1 << (PMD_SHIFT - PTE_SHIFT)) + +/* Section */ +#define SECTION_SHIFT PMD_SHIFT +#define SECTION_SIZE (1UL << SECTION_SHIFT) +#define SECTION_MASK (~(SECTION_SIZE - 1)) + +// Level 3 descriptor PTE高位属性 +#define PTE_TYPE_MASK (3UL << 0) +#define PTE_TYPE_FAULT (0UL << 0) +#define PTE_TYPE_PAGE (3UL << 0) +#define PTE_TABLE_BIT (1UL << 1) +#define PTE_USER (1UL << 6) /* AP[1] */ +#define PTE_RDONLY (1UL << 7) /* AP[2] */ +#define PTE_SHARED (3UL << 8) /* SH[1:0], inner shareable */ +#define PTE_AF (1UL << 10) /* Access Flag */ +#define PTE_NG (1UL << 11) /* nG */ +#define PTE_DBM (1UL << 51) /* Dirty Bit Management */ +#define PTE_CONT (1UL << 52) /* Contiguous range */ +#define PTE_PXN (1UL << 53) /* Privileged XN */ +#define PTE_UXN (1UL << 54) /* User XN */ +#define PTE_HYP_XN (1UL << 54) /* HYP XN */ + +/* + * AttrIndx[2:0] encoding + * (mapping attributes defined in the MAIR* registers). + */ +#define PTE_ATTRINDX(t) ((t) << 2) +#define PTE_ATTRINDX_MASK (7 << 2) + +// #define TCR_IPS_MASK (0x7UL << 32) +// #define TCR_TG1_MASK (0x3UL << 30) +// #define TCR_T1SZ_MASK (0x3fUL << 16) +// #define TCR_TG0_MASK (0x3UL << 14) +// #define TCR_T0SZ_MASK (0x3fUL << 0) + +#define SCTLR_M_MASK (0x1UL << 0) +#define SCTLR_I_MASK (0x1UL << 12) +#define SCTRL_C_MASK (0x1UL << 2) + +/* + * Memory types available. + */ +#define MT_DEVICE_nGnRnE 0 +#define MT_DEVICE_nGnRE 1 +#define MT_DEVICE_GRE 2 +#define MT_NORMAL_NC 3 +#define MT_NORMAL 4 +#define MT_NORMAL_WT 5 + +/* + * Software defined PTE bits definition. + */ +#define PTE_VALID (1UL << 0) +#define PTE_WRITE (PTE_DBM) /* same as DBM (51) */ +#define PTE_DIRTY (1UL << 55) +#define PTE_SPECIAL (1UL << 56) +#define PTE_PROT_NONE (1UL << 58) /* only when !PTE_VALID */ + +#define MAIR(attr, mt) ((attr) << ((mt) * 8)) + +#define _PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED) +#define PROT_DEFAULT (_PROT_DEFAULT) + +#define PAGE_KERNEL_RO ((PROT_NORMAL & ~PTE_WRITE) | PTE_RDONLY) +#define PAGE_KERNEL_ROX ((PROT_NORMAL & ~(PTE_WRITE | PTE_PXN)) | PTE_RDONLY) +#define PAGE_KERNEL_EXEC (PROT_NORMAL & ~PTE_PXN) + +#define PROT_DEVICE_nGnRnE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRnE)) +#define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRE)) +#define PROT_NORMAL_NC (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_NC)) +#define PROT_NORMAL_WT (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_WT)) +#define PROT_NORMAL (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL)) + +#define PAGE_KERNEL PROT_NORMAL + +/* + * TCR flags. + */ +#define TCR_T0SZ_OFFSET 0 +#define TCR_T1SZ_OFFSET 16 +#define TCR_T0SZ(x) ((UL(64) - (x)) << TCR_T0SZ_OFFSET) +#define TCR_T1SZ(x) ((UL(64) - (x)) << TCR_T1SZ_OFFSET) +#define TCR_TxSZ(x) (TCR_T0SZ(x) | TCR_T1SZ(x)) +#define TCR_TxSZ_WIDTH 6 +// #define TCR_T0SZ_MASK (((UL(1) << TCR_TxSZ_WIDTH) - 1) << TCR_T0SZ_OFFSET) + +#define TCR_EPD0_SHIFT 7 +#define TCR_EPD0_MASK (UL(1) << TCR_EPD0_SHIFT) +#define TCR_IRGN0_SHIFT 8 +#define TCR_IRGN0_MASK (UL(3) << TCR_IRGN0_SHIFT) +#define TCR_IRGN0_NC (UL(0) << TCR_IRGN0_SHIFT) +#define TCR_IRGN0_WBWA (UL(1) << TCR_IRGN0_SHIFT) +#define TCR_IRGN0_WT (UL(2) << TCR_IRGN0_SHIFT) +#define TCR_IRGN0_WBnWA (UL(3) << TCR_IRGN0_SHIFT) + +#define TCR_EPD1_SHIFT 23 +#define TCR_EPD1_MASK (UL(1) << TCR_EPD1_SHIFT) +#define TCR_IRGN1_SHIFT 24 +#define TCR_IRGN1_MASK (UL(3) << TCR_IRGN1_SHIFT) +#define TCR_IRGN1_NC (UL(0) << TCR_IRGN1_SHIFT) +#define TCR_IRGN1_WBWA (UL(1) << TCR_IRGN1_SHIFT) +#define TCR_IRGN1_WT (UL(2) << TCR_IRGN1_SHIFT) +#define TCR_IRGN1_WBnWA (UL(3) << TCR_IRGN1_SHIFT) + +#define TCR_IRGN_NC (TCR_IRGN0_NC | TCR_IRGN1_NC) +#define TCR_IRGN_WBWA (TCR_IRGN0_WBWA | TCR_IRGN1_WBWA) +#define TCR_IRGN_WT (TCR_IRGN0_WT | TCR_IRGN1_WT) +#define TCR_IRGN_WBnWA (TCR_IRGN0_WBnWA | TCR_IRGN1_WBnWA) +#define TCR_IRGN_MASK (TCR_IRGN0_MASK | TCR_IRGN1_MASK) + +#define TCR_ORGN0_SHIFT 10 +#define TCR_ORGN0_MASK (UL(3) << TCR_ORGN0_SHIFT) +#define TCR_ORGN0_NC (UL(0) << TCR_ORGN0_SHIFT) +#define TCR_ORGN0_WBWA (UL(1) << TCR_ORGN0_SHIFT) +#define TCR_ORGN0_WT (UL(2) << TCR_ORGN0_SHIFT) +#define TCR_ORGN0_WBnWA (UL(3) << TCR_ORGN0_SHIFT) + +#define TCR_ORGN1_SHIFT 26 +#define TCR_ORGN1_MASK (UL(3) << TCR_ORGN1_SHIFT) +#define TCR_ORGN1_NC (UL(0) << TCR_ORGN1_SHIFT) +#define TCR_ORGN1_WBWA (UL(1) << TCR_ORGN1_SHIFT) +#define TCR_ORGN1_WT (UL(2) << TCR_ORGN1_SHIFT) +#define TCR_ORGN1_WBnWA (UL(3) << TCR_ORGN1_SHIFT) + +#define TCR_ORGN_NC (TCR_ORGN0_NC | TCR_ORGN1_NC) +#define TCR_ORGN_WBWA (TCR_ORGN0_WBWA | TCR_ORGN1_WBWA) +#define TCR_ORGN_WT (TCR_ORGN0_WT | TCR_ORGN1_WT) +#define TCR_ORGN_WBnWA (TCR_ORGN0_WBnWA | TCR_ORGN1_WBnWA) +#define TCR_ORGN_MASK (TCR_ORGN0_MASK | TCR_ORGN1_MASK) + +#define TCR_SH0_SHIFT 12 +#define TCR_SH0_MASK (UL(3) << TCR_SH0_SHIFT) +#define TCR_SH0_INNER (UL(3) << TCR_SH0_SHIFT) + +#define TCR_SH1_SHIFT 28 +#define TCR_SH1_MASK (UL(3) << TCR_SH1_SHIFT) +#define TCR_SH1_INNER (UL(3) << TCR_SH1_SHIFT) +#define TCR_SHARED (TCR_SH0_INNER | TCR_SH1_INNER) + +#define TCR_TG0_SHIFT 14 +#define TCR_TG0_MASK (UL(3) << TCR_TG0_SHIFT) +#define TCR_TG0_4K (UL(0) << TCR_TG0_SHIFT) +#define TCR_TG0_64K (UL(1) << TCR_TG0_SHIFT) +#define TCR_TG0_16K (UL(2) << TCR_TG0_SHIFT) + +#define TCR_TG1_SHIFT 30 +#define TCR_TG1_MASK (UL(3) << TCR_TG1_SHIFT) +#define TCR_TG1_16K (UL(1) << TCR_TG1_SHIFT) +#define TCR_TG1_4K (UL(2) << TCR_TG1_SHIFT) +#define TCR_TG1_64K (UL(3) << TCR_TG1_SHIFT) + +#define TCR_IPS_SHIFT 32 +#define TCR_IPS_MASK (UL(7) << TCR_IPS_SHIFT) +#define TCR_A1 (UL(1) << 22) +#define TCR_ASID16 (UL(1) << 36) +#define TCR_TBI0 (UL(1) << 37) +#define TCR_TBI1 (UL(1) << 38) +#define TCR_HA (UL(1) << 39) +#define TCR_HD (UL(1) << 40) +#define TCR_NFD1 (UL(1) << 54) + +#define TCR_TG_FLAGS (TCR_TG0_4K | TCR_TG1_4K) +#define TCR_KASLR_FLAGS 0 +#define TCR_KASAN_FLAGS 0 +#define TCR_SMP_FLAGS TCR_SHARED +#define TCR_CACHE_FLAGS (TCR_IRGN_WBWA | TCR_ORGN_WBWA) + +#define TCR_48BITS (((64 - VA_BITS) << 0) | ((64 - VA_BITS) << 16)) +#define TCR_IPS_48BITS (ID_AA64MMFR0_PARANGE_48 << 32) + +/* id_aa64mmfr0 */ +#define ID_AA64MMFR0_TGRAN4_SHIFT 28 +#define ID_AA64MMFR0_TGRAN64_SHIFT 24 +#define ID_AA64MMFR0_TGRAN16_SHIFT 20 +#define ID_AA64MMFR0_BIGENDEL0_SHIFT 16 +#define ID_AA64MMFR0_SNSMEM_SHIFT 12 +#define ID_AA64MMFR0_BIGENDEL_SHIFT 8 +#define ID_AA64MMFR0_ASID_SHIFT 4 +#define ID_AA64MMFR0_PARANGE_SHIFT 0 + +#define ID_AA64MMFR0_TGRAN4_NI 0xf +#define ID_AA64MMFR0_TGRAN4_SUPPORTED 0x0 +#define ID_AA64MMFR0_TGRAN64_NI 0xf +#define ID_AA64MMFR0_TGRAN64_SUPPORTED 0x0 +#define ID_AA64MMFR0_TGRAN16_NI 0x0 +#define ID_AA64MMFR0_TGRAN16_SUPPORTED 0x1 +#define ID_AA64MMFR0_PARANGE_48 0x5 +#define ID_AA64MMFR0_PARANGE_52 0x6 + +#if defined(CONFIG_ARM64_4K_PAGES) +#define ID_AA64MMFR0_TGRAN_SHIFT ID_AA64MMFR0_TGRAN4_SHIFT +#define ID_AA64MMFR0_TGRAN_SUPPORTED ID_AA64MMFR0_TGRAN4_SUPPORTED +#endif + +#define PTE_ADDR_LOW (((1UL << (48 - PAGE_SHIFT)) - 1) << PAGE_SHIFT) +#define PTE_ADDR_MASK PTE_ADDR_LOW + +void paging_init(void); diff --git a/mkrtos_knl/arch/aarch64/pre_cpu.c b/mkrtos_knl/arch/aarch64/pre_cpu.c new file mode 100644 index 000000000..859c3ac71 --- /dev/null +++ b/mkrtos_knl/arch/aarch64/pre_cpu.c @@ -0,0 +1,50 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#if CONFIG_SMP +extern char _pre_cpu_data_start[]; +extern char _pre_cpu_data_end[]; + +static void *pre_cpu_data; +static mword_t pre_cpu_data_size; + +void pre_cpu_init(void) +{ + mword_t data_size = (addr_t)_pre_cpu_data_end - (addr_t)_pre_cpu_data_start; + pre_cpu_data_size = ALIGN(data_size, MWORD_BYTES); + + printk("pre_cpu data's size is %d bytes.\n", data_size);\ + printk("pre_cpu data's alloc size is %d bytes.\n", pre_cpu_data_size); + + pre_cpu_data = buddy_alloc(buddy_get_alloter(), + pre_cpu_data_size * SYS_CPU_NUM); + assert(pre_cpu_data); + memset(pre_cpu_data, 0, pre_cpu_data_size * SYS_CPU_NUM); +} +#else +void pre_cpu_init(void) +{ +} +#endif + +void *pre_cpu_get_var_cpu(int cpu_inx, void *mem_addr) +{ + #if CONFIG_SMP + mword_t offset = (addr_t)mem_addr - (addr_t)_pre_cpu_data_start; + + return (void *)((addr_t)pre_cpu_data + + offset + cpu_inx * pre_cpu_data_size); + #else + return mem_addr; + #endif +} +void *pre_cpu_get_current_cpu_var(void *mem_addr) +{ + return pre_cpu_get_var_cpu(arch_get_current_cpu_id(), mem_addr); +} diff --git a/mkrtos_knl/arch/aarch64/pre_cpu.h b/mkrtos_knl/arch/aarch64/pre_cpu.h new file mode 100644 index 000000000..d29f1278d --- /dev/null +++ b/mkrtos_knl/arch/aarch64/pre_cpu.h @@ -0,0 +1,12 @@ + +#pragma once + +#include + +#define PER_CPU(type, name) \ + __attribute__((used)) \ + SECTION(".data.per_cpu") type name + +void pre_cpu_init(void); +void *pre_get_current_cpu_var(void *mem_addr); +void *pre_get_var_cpu(int cpu_inx, void *mem_addr); diff --git a/mkrtos_knl/arch/aarch64/psci.c b/mkrtos_knl/arch/aarch64/psci.c new file mode 100644 index 000000000..105e1de14 --- /dev/null +++ b/mkrtos_knl/arch/aarch64/psci.c @@ -0,0 +1,137 @@ + +#include +#include +#include +enum +{ + PSCI_FUNC_VERSION = 0, + PSCI_FUNC_CPU_SUSPEND, + PSCI_FUNC_CPU_OFF, + PSCI_FUNC_CPU_ON, + PSCI_FUNC_AFFINITY_INFO, + PSCI_FUNC_MIGRATE, + PSCI_FUNC_MIGRATE_INFO_TYPE, + PSCI_FUNC_MIGRATE_INFO_UP_CPU, + PSCI_FUNC_SYSTEM_OFF, + PSCI_FUNC_SYSTEM_RESET, + PSCI_FUNC_FEATURES, + PSCI_FUNC_CPU_FREEZE, + PSCI_FUNC_CPU_DEFAULT_SUSPEND, + PSCI_FUNC_NODE_HW_STATE, + PSCI_FUNC_SYSTEM_SUSPEND, + PSCI_FUNC_SET_SUSPEND_MODE, + PSCI_FUNC_STAT_RESIDENCY, + PSCI_FUNC_STAT_COUNT, + + PSCI_FUNC_BASE_SMC32 = 0x84000000, + PSCI_FUNC_BASE_SMC64 = 0xC4000000, +}; +static int v1; +static umword_t psci_func(umword_t func_id) +{ + switch (func_id) + { + case PSCI_FUNC_VERSION: + case PSCI_FUNC_CPU_OFF: + case PSCI_FUNC_MIGRATE_INFO_TYPE: + case PSCI_FUNC_SYSTEM_OFF: + case PSCI_FUNC_SYSTEM_RESET: + case PSCI_FUNC_FEATURES: + case PSCI_FUNC_CPU_FREEZE: + case PSCI_FUNC_SET_SUSPEND_MODE: + return PSCI_FUNC_BASE_SMC32 + func_id; + default: + return ((sizeof(long) == 8) ? PSCI_FUNC_BASE_SMC64 : PSCI_FUNC_BASE_SMC32) + func_id; + } +} + +static inline void psci_call( + umword_t func_id, + umword_t res[4], + umword_t arg0, + umword_t arg1, + umword_t arg2, + umword_t arg3, + umword_t arg4, + umword_t arg5, + umword_t arg6) +{ + register umword_t r0 asm("x0") = psci_func(func_id); + register umword_t r1 asm("x1") = arg0; + register umword_t r2 asm("x2") = arg1; + register umword_t r3 asm("x3") = arg2; + register umword_t r4 asm("x4") = arg3; + register umword_t r5 asm("x5") = arg4; + register umword_t r6 asm("x6") = arg5; + register umword_t r7 asm("x7") = arg6; + + // asm volatile("smc #0"); + arm_smc(r0, r1, r2, r3, r4, r5, r6, r7); + + res[0] = r0; + res[1] = r1; + res[2] = r2; + res[3] = r3; +} +void psci_init(void) +{ + umword_t res[4]; + + printk("psci detecting..\n"); + psci_call( + PSCI_FUNC_VERSION, res, 0, 0, 0, + 0, 0, 0, 0); + v1 = (res[0] >> 16) >= 1; + + if (v1) + { + psci_call(PSCI_FUNC_FEATURES, res, + psci_func(PSCI_FUNC_CPU_SUSPEND), + 0, 0, 0, 0, 0, 0); + if (res[0] & (1UL << 31)) + { + printk("psci CPU_SUSPEND not supported (%d)\n", (int)res[0]); + } + else + { + printk("psci CPU_SUSPEND format %s, %s support OS-initiated mode\n", + res[0] & 0x2 ? "extended" : "original v0.2", + res[0] & 0x1 ? "" : "not"); + } + } + psci_call(PSCI_FUNC_MIGRATE_INFO_TYPE, res, + 0, 0, 0, 0, 0, 0, 0); + if (res[0] == 0 || res[0] == 1) + { + printk("psci TOS:single core, %s migration capable\n", + res[0] ? "not " : ""); + } + else + { + printk("psci TOS:not present or not required\n"); + } +} +umword_t psci_cpu_on(umword_t cpuid, umword_t entry_point) +{ + umword_t res[4]; + + psci_call(PSCI_FUNC_CPU_ON, res, cpuid, entry_point, + 0, 0, 0, 0, 0); + return res[0]; +} +void psci_system_reset(void) +{ + umword_t res[4]; + + psci_call(PSCI_FUNC_SYSTEM_RESET, res, + 0, 0, 0, 0, 0, 0, 0); + printk("psci system-reset failed.\n"); +} +void psic_system_off(void) +{ + umword_t res[4]; + + psci_call(PSCI_FUNC_SYSTEM_OFF, res, + 0, 0, 0, 0, 0, 0, 0); + printk("psci system_off failed.\n"); +} diff --git a/mkrtos_knl/arch/aarch64/psci.h b/mkrtos_knl/arch/aarch64/psci.h new file mode 100644 index 000000000..7050f0848 --- /dev/null +++ b/mkrtos_knl/arch/aarch64/psci.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +void psci_init(void); +umword_t psci_cpu_on(umword_t cpuid, umword_t entry_point); +void psci_system_reset(void); +void psic_system_off(void); +void arm_smc(umword_t arg0, + umword_t arg1, + umword_t arg2, + umword_t arg3, + umword_t arg4, + umword_t arg5, + umword_t arg6, + umword_t arg7); diff --git a/mkrtos_knl/arch/aarch64/psci_asm.S b/mkrtos_knl/arch/aarch64/psci_asm.S new file mode 100644 index 000000000..b9d363f92 --- /dev/null +++ b/mkrtos_knl/arch/aarch64/psci_asm.S @@ -0,0 +1,9 @@ + +#include + +.section ".text" + +BEGIN_FUNC(arm_smc) + smc #0 + ret +END_FUNC(arm_smc) diff --git a/mkrtos_knl/arch/aarch64/spin_table.c b/mkrtos_knl/arch/aarch64/spin_table.c new file mode 100644 index 000000000..6e4fabd53 --- /dev/null +++ b/mkrtos_knl/arch/aarch64/spin_table.c @@ -0,0 +1,58 @@ + + +// #include +#include +#include +#include +#include +#define DATA_BOOT_SECTION ".data.boot" +#define TEXT_BOOT_SECTION ".text.boot" + +extern mword_t cpu_jump_addr[SYS_CPU_NUM]; +extern mword_t per_cpu_stack_addr[SYS_CPU_NUM]; + +// 每个cpu的栈指针 +SECTION(DATA_BOOT_SECTION) +__ALIGN__(PAGE_SIZE) +mword_t per_cpu_stack[SYS_CPU_NUM][THREAD_BLOCK_SIZE / MWORD_BYTES]; + +void *get_cpu_stack(int cpu_inx) +{ + return (void *)per_cpu_stack[cpu_inx]; +} + +static inline SECTION(TEXT_BOOT_SECTION) uint64_t get_st_currentel(void) +{ + unsigned long _val; + + asm volatile("mrs %0, CurrentEL" + : "=r"(_val)); + return _val; +} +static SECTION(TEXT_BOOT_SECTION) inline int boot_get_current_cpu_id(void) +{ + return read_sysreg(mpidr_el1) & 0XFFUL; +} + +extern void cpu_kernel_init(void); +void SECTION(TEXT_BOOT_SECTION) other_cpu_boot(void) +{ + // int cpu_id; + + // cpu_id = boot_get_current_cpu_id(); + // per_cpu_boot_mapping(&per_cpu_pkdir[cpu_id - 1]); + per_cpu_boot_mapping(FALSE); + + mword_t elx = get_st_currentel(); + + // kprint("cpuid %d run el%d.\n", cpu_id, elx); + cpu_kernel_init(); + while (1) + ; +} +void SECTION(TEXT_BOOT_SECTION) cpu_start_to(int cpu_id) +{ + // knl_pdir_init(&per_cpu_pkdir[cpu_id - 1], per_cpu_boot_kpdir[cpu_id - 1]); + per_cpu_stack_addr[cpu_id] = ((addr_t)per_cpu_stack[cpu_id]) + THREAD_BLOCK_SIZE - MWORD_BYTES - PT_REGS_SIZE; + cpu_jump_addr[cpu_id] = (mword_t)other_cpu_boot; +} diff --git a/mkrtos_knl/arch/aarch64/spin_table.h b/mkrtos_knl/arch/aarch64/spin_table.h new file mode 100644 index 000000000..51b417679 --- /dev/null +++ b/mkrtos_knl/arch/aarch64/spin_table.h @@ -0,0 +1,4 @@ +#pragma once + +void cpu_start_to(int cpu_id); +void *get_cpu_stack(int cpu_inx); diff --git a/mkrtos_knl/arch/aarch64/spinlock_arch.c b/mkrtos_knl/arch/aarch64/spinlock_arch.c new file mode 100644 index 000000000..2309ff49d --- /dev/null +++ b/mkrtos_knl/arch/aarch64/spinlock_arch.c @@ -0,0 +1,28 @@ + +#include +#include + +void spinlock_lock_arch(spinlock_t *lock) +{ + mword_t dummy; + mword_t tmp; + + asm volatile( + "sevl\n" + "prfm pstl1keep, [%[lock]]\n" + "1: wfe\n" + "ldaxr %x[dummy],[%[lock]]\n" + "cbnz %x[dummy],1b\n" + "orr %x[tmp],%x[dummy],#1\n" + "stxr %w[dummy], %x[tmp], [%[lock]]\n" + "cbnz %w[dummy],1b\n" + : [dummy] "=&r"(dummy), [tmp] "=&r"(tmp), "+m"(lock->val) + : [lock] "r"(&lock->val) + : "cc"); +} +void spinlock_unlock_arch(spinlock_t *lock) +{ + asm volatile( + "stlr wzr, %[lock]" + : [lock] "=Q"(lock->val)); +} diff --git a/mkrtos_knl/arch/aarch64/spinlock_arch.h b/mkrtos_knl/arch/aarch64/spinlock_arch.h new file mode 100644 index 000000000..176c4af01 --- /dev/null +++ b/mkrtos_knl/arch/aarch64/spinlock_arch.h @@ -0,0 +1,6 @@ +#pragma once + +#include + +void spinlock_lock_arch(spinlock_t *lock); +void spinlock_unlock_arch(spinlock_t *lock); diff --git a/mkrtos_knl/arch/aarch64/thread_arch.h b/mkrtos_knl/arch/aarch64/thread_arch.h new file mode 100644 index 000000000..b7b41d9de --- /dev/null +++ b/mkrtos_knl/arch/aarch64/thread_arch.h @@ -0,0 +1,3 @@ +#pragma once + +#define THREAD_BLOCK_SIZE CONFIG_THREAD_BLOCK_SIZE //!< 线程块大小,栈在块的顶部 diff --git a/mkrtos_knl/arch/aarch64/thread_armv8.c b/mkrtos_knl/arch/aarch64/thread_armv8.c new file mode 100644 index 000000000..f97ba19ab --- /dev/null +++ b/mkrtos_knl/arch/aarch64/thread_armv8.c @@ -0,0 +1,56 @@ + + +#include +#include +#include +umword_t thread_get_pfa(void) +{ + umword_t a; + + asm volatile("mrs %0, far_el2" : "=r"(a)); + return a; +} +void thread_sync_entry(entry_frame_t *regs) +{ + umword_t ec = 0; + // umword_t ec = arm_esr_ec(esr_get()); + // thread_t *th = thread_current(); + // task_t *tk = (task_t *)th->task; + + switch (ec) + { + case 0x20: + { + // mword_t addr = thread_get_pfa(); + + // if (vma_page_fault(&tk->vmam, &tk->mem_dir, MASK_LSB(addr, PAGE_SHIFT)) == NULL) { + // //TODO: 如果是init进程则内核死机,否则干掉进程 + // MKRTOS_ASSERT(0); + // } + } + return; + case 0x24: + { + // mword_t addr = thread_get_pfa(); + + // if (vma_page_fault(&tk->vmam, &tk->mem_dir, MASK_LSB(addr, PAGE_SHIFT)) == NULL) { + // //TODO: 如果是init进程则内核死机,否则干掉进程 + // MKRTOS_ASSERT(0); + // } + } + return; + case 0x12: + case 0x11: + case 0x15: + case 0x16: + // svc_handler(regs); + return; + case 0x00: + return; + case 0x07: + break; + case 0x03: + default: + break; + } +} diff --git a/mkrtos_knl/arch/armv7m/CMakeLists.txt b/mkrtos_knl/arch/cortex-m3/CMakeLists.txt similarity index 51% rename from mkrtos_knl/arch/armv7m/CMakeLists.txt rename to mkrtos_knl/arch/cortex-m3/CMakeLists.txt index e2406f795..d87e8b6d2 100755 --- a/mkrtos_knl/arch/armv7m/CMakeLists.txt +++ b/mkrtos_knl/arch/cortex-m3/CMakeLists.txt @@ -1,18 +1,24 @@ cmake_minimum_required(VERSION 3.13) file(GLOB deps *.c *.S) +list(REMOVE_ITEM deps ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/${CONFIG_ARCH}/link.lds.S) add_library(arch STATIC ${deps}) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D__MPU_PRESENT=1 -DUSE_STDPERIPH_DRIVER=1 ") message(=======${CONFIG_CPU_TYPE}) - +target_include_directories( + arch + PUBLIC + ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/${CONFIG_ARCH}/${CONFIG_CPU_TYPE} + ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/${CONFIG_ARCH}/ +) if (${CONFIG_CPU_TYPE} STREQUAL "stm32f1") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DSTM32F10X_XL ") target_include_directories( arch PUBLIC - ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/armv7m/${CONFIG_CPU_TYPE} + ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/${CONFIG_ARCH}/${CONFIG_CPU_TYPE} ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/knl ${CMAKE_SOURCE_DIR}/mkrtos_bsp/STM32/STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/STM32F10x_StdPeriph_Driver/inc @@ -20,38 +26,14 @@ if (${CONFIG_CPU_TYPE} STREQUAL "stm32f1") ) add_subdirectory(${CONFIG_CPU_TYPE}) elseif(${CONFIG_CPU_TYPE} STREQUAL "stm32f2" ) +# message(======="${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/${CONFIG_ARCH}/${CONFIG_CPU_TYPE}") target_include_directories( arch PUBLIC - ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/armv7m/${CONFIG_CPU_TYPE} + ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/${CONFIG_ARCH}/${CONFIG_CPU_TYPE} ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/knl ${CMAKE_SOURCE_DIR}/mkrtos_bsp/STM32/STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/STM32F2xx_StdPeriph_Driver/inc - - ) - add_subdirectory(${CONFIG_CPU_TYPE}) -elseif(${CONFIG_CPU_TYPE} STREQUAL "stm32f4" ) - if(${BOARD} STREQUAL "STM32F407VET6" ) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DSTM32F40_41xxx ") - endif() - target_include_directories( - arch - PUBLIC - ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/armv7m/${CONFIG_CPU_TYPE} - ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/knl - - ${CMAKE_SOURCE_DIR}/mkrtos_bsp/STM32/STM32F4xx_DSP_StdPeriph_Lib_V1.9.0/Libraries/STM32F4xx_StdPeriph_Driver/inc - ) - add_subdirectory(${CONFIG_CPU_TYPE}) -elseif(${CONFIG_CPU_TYPE} STREQUAL "swm34s" ) - - include_directories( - ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/armv7m/${CONFIG_CPU_TYPE} - ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/knl - - ${CMAKE_SOURCE_DIR}/mkrtos_bsp/SWM34/SWM341_StdPeriph_Driver/CMSIS/DeviceSupport - ${CMAKE_SOURCE_DIR}/mkrtos_bsp/SWM34/SWM341_StdPeriph_Driver/CMSIS/CoreSupport - ${CMAKE_SOURCE_DIR}/mkrtos_bsp/SWM34/SWM341_StdPeriph_Driver/SWM341_StdPeriph_Driver ) add_subdirectory(${CONFIG_CPU_TYPE}) endif() diff --git a/mkrtos_knl/arch/armv7m/atomic.S b/mkrtos_knl/arch/cortex-m3/atomic.S old mode 100755 new mode 100644 similarity index 100% rename from mkrtos_knl/arch/armv7m/atomic.S rename to mkrtos_knl/arch/cortex-m3/atomic.S diff --git a/mkrtos_knl/arch/armv7m/core_it.c b/mkrtos_knl/arch/cortex-m3/core_it.c similarity index 100% rename from mkrtos_knl/arch/armv7m/core_it.c rename to mkrtos_knl/arch/cortex-m3/core_it.c diff --git a/mkrtos_knl/link.lds b/mkrtos_knl/arch/cortex-m3/link.lds similarity index 100% rename from mkrtos_knl/link.lds rename to mkrtos_knl/arch/cortex-m3/link.lds diff --git a/mkrtos_knl/link.lds.S b/mkrtos_knl/arch/cortex-m3/link.lds.S old mode 100755 new mode 100644 similarity index 100% rename from mkrtos_knl/link.lds.S rename to mkrtos_knl/arch/cortex-m3/link.lds.S diff --git a/mkrtos_knl/arch/armv7m/sche.S b/mkrtos_knl/arch/cortex-m3/sche.S similarity index 100% rename from mkrtos_knl/arch/armv7m/sche.S rename to mkrtos_knl/arch/cortex-m3/sche.S diff --git a/mkrtos_knl/arch/armv7m/stm32f1/CMakeLists.txt b/mkrtos_knl/arch/cortex-m3/stm32f1/CMakeLists.txt similarity index 100% rename from mkrtos_knl/arch/armv7m/stm32f1/CMakeLists.txt rename to mkrtos_knl/arch/cortex-m3/stm32f1/CMakeLists.txt diff --git a/mkrtos_knl/arch/armv7m/stm32f1/arch.c b/mkrtos_knl/arch/cortex-m3/stm32f1/arch.c similarity index 100% rename from mkrtos_knl/arch/armv7m/stm32f1/arch.c rename to mkrtos_knl/arch/cortex-m3/stm32f1/arch.c diff --git a/mkrtos_knl/arch/armv7m/stm32f1/arch.h b/mkrtos_knl/arch/cortex-m3/stm32f1/arch.h similarity index 100% rename from mkrtos_knl/arch/armv7m/stm32f1/arch.h rename to mkrtos_knl/arch/cortex-m3/stm32f1/arch.h diff --git a/mkrtos_knl/arch/armv7m/stm32f1/mk_sys.h b/mkrtos_knl/arch/cortex-m3/stm32f1/mk_sys.h similarity index 100% rename from mkrtos_knl/arch/armv7m/stm32f1/mk_sys.h rename to mkrtos_knl/arch/cortex-m3/stm32f1/mk_sys.h diff --git a/mkrtos_knl/arch/armv7m/stm32f1/mpu.c b/mkrtos_knl/arch/cortex-m3/stm32f1/mpu.c similarity index 100% rename from mkrtos_knl/arch/armv7m/stm32f1/mpu.c rename to mkrtos_knl/arch/cortex-m3/stm32f1/mpu.c diff --git a/mkrtos_knl/arch/armv7m/stm32f1/startup_stm32f10x_xl.s b/mkrtos_knl/arch/cortex-m3/stm32f1/startup_stm32f10x_xl.s similarity index 100% rename from mkrtos_knl/arch/armv7m/stm32f1/startup_stm32f10x_xl.s rename to mkrtos_knl/arch/cortex-m3/stm32f1/startup_stm32f10x_xl.s diff --git a/mkrtos_knl/arch/armv7m/stm32f1/stm32f10x_conf.h b/mkrtos_knl/arch/cortex-m3/stm32f1/stm32f10x_conf.h similarity index 100% rename from mkrtos_knl/arch/armv7m/stm32f1/stm32f10x_conf.h rename to mkrtos_knl/arch/cortex-m3/stm32f1/stm32f10x_conf.h diff --git a/mkrtos_knl/arch/armv7m/stm32f1/stm32f10x_it.h b/mkrtos_knl/arch/cortex-m3/stm32f1/stm32f10x_it.h similarity index 100% rename from mkrtos_knl/arch/armv7m/stm32f1/stm32f10x_it.h rename to mkrtos_knl/arch/cortex-m3/stm32f1/stm32f10x_it.h diff --git a/mkrtos_knl/arch/armv7m/stm32f1/system_stm32f10x.c b/mkrtos_knl/arch/cortex-m3/stm32f1/system_stm32f10x.c similarity index 100% rename from mkrtos_knl/arch/armv7m/stm32f1/system_stm32f10x.c rename to mkrtos_knl/arch/cortex-m3/stm32f1/system_stm32f10x.c diff --git a/mkrtos_knl/arch/armv7m/stm32f2/CMakeLists.txt b/mkrtos_knl/arch/cortex-m3/stm32f2/CMakeLists.txt similarity index 81% rename from mkrtos_knl/arch/armv7m/stm32f2/CMakeLists.txt rename to mkrtos_knl/arch/cortex-m3/stm32f2/CMakeLists.txt index 5b8354734..2b646d088 100755 --- a/mkrtos_knl/arch/armv7m/stm32f2/CMakeLists.txt +++ b/mkrtos_knl/arch/cortex-m3/stm32f2/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.13) -file(GLOB_RECURSE deps **/*.s *.s **/*.C *.c) +file(GLOB_RECURSE deps *.s *.S *.C *.c) file(GLOB bsp_src ${CMAKE_SOURCE_DIR}/mkrtos_bsp/STM32/STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/STM32F2xx_StdPeriph_Driver/src/*.c) list(APPEND deps ${bsp_src}) @@ -12,7 +12,8 @@ target_include_directories( ${CMAKE_SOURCE_DIR}/mkrtos_bsp/STM32/STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/STM32F2xx_StdPeriph_Driver/inc ${CMAKE_SOURCE_DIR}/mkrtos_bsp/STM32/STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/CMSIS/Include ${CMAKE_SOURCE_DIR}/mkrtos_bsp/STM32/STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/CMSIS/Device/ST/STM32F2xx/Include - ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/armv7m/stm32f2 + ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/${CONFIG_ARCH}/${CONFIG_CPU_TYPE} + ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/${CONFIG_ARCH}/ ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/lib ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/knl ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/inc diff --git a/mkrtos_knl/arch/armv7m/stm32f2/arch.c b/mkrtos_knl/arch/cortex-m3/stm32f2/arch.c similarity index 100% rename from mkrtos_knl/arch/armv7m/stm32f2/arch.c rename to mkrtos_knl/arch/cortex-m3/stm32f2/arch.c diff --git a/mkrtos_knl/arch/armv7m/stm32f2/arch.h b/mkrtos_knl/arch/cortex-m3/stm32f2/arch.h similarity index 100% rename from mkrtos_knl/arch/armv7m/stm32f2/arch.h rename to mkrtos_knl/arch/cortex-m3/stm32f2/arch.h diff --git a/mkrtos_knl/arch/armv7m/stm32f2/entry.S b/mkrtos_knl/arch/cortex-m3/stm32f2/entry.S similarity index 100% rename from mkrtos_knl/arch/armv7m/stm32f2/entry.S rename to mkrtos_knl/arch/cortex-m3/stm32f2/entry.S diff --git a/mkrtos_knl/arch/armv7m/stm32f2/mk_sys.h b/mkrtos_knl/arch/cortex-m3/stm32f2/mk_sys.h similarity index 100% rename from mkrtos_knl/arch/armv7m/stm32f2/mk_sys.h rename to mkrtos_knl/arch/cortex-m3/stm32f2/mk_sys.h diff --git a/mkrtos_knl/arch/armv7m/stm32f2/mpu.c b/mkrtos_knl/arch/cortex-m3/stm32f2/mpu.c similarity index 100% rename from mkrtos_knl/arch/armv7m/stm32f2/mpu.c rename to mkrtos_knl/arch/cortex-m3/stm32f2/mpu.c diff --git a/mkrtos_knl/arch/armv7m/stm32f2/stm32f2xx_conf.h b/mkrtos_knl/arch/cortex-m3/stm32f2/stm32f2xx_conf.h similarity index 100% rename from mkrtos_knl/arch/armv7m/stm32f2/stm32f2xx_conf.h rename to mkrtos_knl/arch/cortex-m3/stm32f2/stm32f2xx_conf.h diff --git a/mkrtos_knl/arch/armv7m/stm32f2/stm32f2xx_it.h b/mkrtos_knl/arch/cortex-m3/stm32f2/stm32f2xx_it.h similarity index 100% rename from mkrtos_knl/arch/armv7m/stm32f2/stm32f2xx_it.h rename to mkrtos_knl/arch/cortex-m3/stm32f2/stm32f2xx_it.h diff --git a/mkrtos_knl/arch/armv7m/stm32f2/system_stm32f2xx.c b/mkrtos_knl/arch/cortex-m3/stm32f2/system_stm32f2xx.c similarity index 100% rename from mkrtos_knl/arch/armv7m/stm32f2/system_stm32f2xx.c rename to mkrtos_knl/arch/cortex-m3/stm32f2/system_stm32f2xx.c diff --git a/mkrtos_knl/arch/armv7m/syscall.S b/mkrtos_knl/arch/cortex-m3/syscall.S similarity index 100% rename from mkrtos_knl/arch/armv7m/syscall.S rename to mkrtos_knl/arch/cortex-m3/syscall.S diff --git a/mkrtos_knl/arch/cortex-m3/thread_arch.h b/mkrtos_knl/arch/cortex-m3/thread_arch.h new file mode 100644 index 000000000..b7b41d9de --- /dev/null +++ b/mkrtos_knl/arch/cortex-m3/thread_arch.h @@ -0,0 +1,3 @@ +#pragma once + +#define THREAD_BLOCK_SIZE CONFIG_THREAD_BLOCK_SIZE //!< 线程块大小,栈在块的顶部 diff --git a/mkrtos_knl/arch/cortex-m33/CMakeLists.txt b/mkrtos_knl/arch/cortex-m33/CMakeLists.txt new file mode 100755 index 000000000..d1ec5cace --- /dev/null +++ b/mkrtos_knl/arch/cortex-m33/CMakeLists.txt @@ -0,0 +1,35 @@ +cmake_minimum_required(VERSION 3.13) + +file(GLOB deps *.c *.S) + +add_library(arch STATIC ${deps}) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D__MPU_PRESENT=1 -DUSE_STDPERIPH_DRIVER=1 ") +message(=======${CONFIG_CPU_TYPE}) + +if (${CONFIG_CPU_TYPE} STREQUAL "swm34s" ) + + include_directories( + ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/${ARCH}/${CONFIG_CPU_TYPE} + ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/knl + + ${CMAKE_SOURCE_DIR}/mkrtos_bsp/SWM34/SWM341_StdPeriph_Driver/CMSIS/DeviceSupport + ${CMAKE_SOURCE_DIR}/mkrtos_bsp/SWM34/SWM341_StdPeriph_Driver/CMSIS/CoreSupport + ${CMAKE_SOURCE_DIR}/mkrtos_bsp/SWM34/SWM341_StdPeriph_Driver/SWM341_StdPeriph_Driver + ) + add_subdirectory(${CONFIG_CPU_TYPE}) + +endif() + +target_link_libraries( + arch + PUBLIC + knl_bsp +) +target_include_directories( + arch + PUBLIC + ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/inc + ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/lib + ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/knl +) diff --git a/mkrtos_knl/arch/cortex-m33/atomic.S b/mkrtos_knl/arch/cortex-m33/atomic.S new file mode 100644 index 000000000..da2369a39 --- /dev/null +++ b/mkrtos_knl/arch/cortex-m33/atomic.S @@ -0,0 +1,287 @@ +.syntax unified +@ .cpu cortex-m3 +.thumb + +.global atomic_inc +.section .text.atomic_inc +.type atomic_inc, %function +atomic_inc: + MOV R3,#0 + TryInc: + LDREX r2, [R0] + ADD r2, #1 + CMP R2,#0 + BEQ incN + B incN1 + incN: + MOV R3,#1 + incN1: + STREX R1, R2, [R0] + CMP R1, #1 //检查 STREX 是否被驳回 + BEQ TryInc //重新尝试 + MOV R0,R3 + bx lr + +.global atomic_dec +.section .text.atomic_dec +.type atomic_dec, %function +atomic_dec: + MOV R3,#0 + TryDec: + LDREX r2, [R0] + ADD r2, #-1 + CMP R2,#0 + BEQ decN + B decN1 + decN: + MOV R3,#1 + decN1: + STREX R1, R2, [R0] + CMP R1, #1 //检查 STREX 是否被驳回 + + BEQ TryDec //重新尝试 + + bx lr +.global atomic_set +.section .text.atomic_set +.type atomic_set, %function +atomic_set: +TrySet: + LDREX r2, [R0] + MOV r2, R1 + STREX R3, R2, [R0] + CMP R3, #1 //检查 STREX 是否被驳回 + BEQ TrySet //重新尝试 + + bx lr + +.global atomic_ret_set +.section .text.atomic_ret_set +.type atomic_ret_set, %function +atomic_ret_set: + push {r4} +TryRetSet: + LDREX r2, [R0] + mov r4,r2 + MOV r2, R1 + STREX R3, R2, [R0] + CMP R3, #1 //检查 STREX 是否被驳回 + BEQ TryRetSet //重新尝试 + mov r0,r4 + pop {r4} + bx lr + +.global atomic_read +.section .text.atomic_read +.type atomic_read, %function +atomic_read: + LDR R0, [R0] + BX LR + +.global atomic_add +.section .text.atomic_add +.type atomic_add, %function +atomic_add: + MOV R3,R1 +TryAdd: + LDREX r2, [R0] + ADD r2, R3 + STREX R1, R2, [R0] + CMP R1, #1 //检查 STREX 是否被驳回 + BEQ TryAdd //重新尝试 + BX LR + +.global atomic_sub +.section .text.atomic_sub +.type atomic_sub, %function +atomic_sub: + MOV R3,R1 +TrySub: + LDREX r2, [R0] + SUB r2, R3 + STREX R1, R2, [R0] + CMP R1, #1 //检查 STREX 是否被驳回 + BEQ TrySub //重新尝试 + BX LR + +.global atomic_test +.section .text.atomic_test +.type atomic_test, %function +atomic_test: + push {r4} +TryTest: + LDREX r2, [R0] + CMP R2,r1 //比较是否等于 + BEQ FZTest //等于则跳转到赋值 + MOV R4,#0 + B FZETest +FZTest: + MOV R4,#1 +FZETest: + STREX R3, R2, [R0] + CMP R3, #1 //检查 STREX 是否被驳回 + + BEQ TryTest //重新尝试 + MOV R0,R4 + pop {r4} + bx lr + +.global atomic_test_set +.section .text.atomic_test_set +.type atomic_test_set, %function +atomic_test_set: + push {r4} +TryTestSet: + LDREX r2, [R0] + CMP R2,#0 //比较是否等于0 + BEQ FZTestSet //等于0则跳转到赋值 + MOV R4,#0 + B FZETestSet +FZTestSet: + MOV R4,#1 + MOV r2, R1 //等于零则进行赋值 +FZETestSet: + STREX R3, R2, [R0] + CMP R3, #1 //检查 STREX 是否被驳回 + + BEQ TryTestSet //重新尝试 + MOV R0,R4 + pop {r4} + bx lr + +.global atomic_set_test +.section .text.atomic_set_test +.type atomic_set_test, %function +atomic_set_test: + push {r4} +TrySetTest: + LDREX r2, [R0] + CMP R2,#0 //比较是否等于0 + BEQ FZSetTest //等于0则跳转到赋值 + MOV R4,#0 + B FZESetTest +FZSetTest: + MOV R4,#1 + +FZESetTest: + MOV r2, R1 //等于零则进行赋值 + STREX R3, R2, [R0] + CMP R3, #1 //检查 STREX 是否被驳回 + + BEQ TrySetTest //重新尝试 + MOV R0,R4 + pop {r4} + bx lr + +.global atomic_inc_test +.section .text.atomic_inc_test +.type atomic_inc_test, %function +atomic_inc_test: + push {r4} + TryIncTest: + LDREX r2, [R0] + CMP R2,#0 //比较是否等于0 + BEQ FZIncTest //等于0则跳转到赋值 + MOV R4,#0 + B FZEIncTest + FZIncTest: + MOV R4,#1 + FZEIncTest: + ADD R2,R2,#1 + STREX R3, R2, [R0] + CMP R3, #1 //检查 STREX 是否被驳回 + + BEQ TryIncTest //重新尝试 + MOV R0,R4 + pop {r4} + bx lr + + +.global atomic_test_inc +.section .text.atomic_test_inc +.type atomic_test_inc, %function +atomic_test_inc: + push {r4} +TryTestInc: + LDREX r2, [R0] + CMP R2,#0 //比较是否等于0 + BEQ FZTestInc //等于0则跳转到赋值 + MOV R4,#0 + B FZETestInc +FZTestInc: + MOV R4,#1 + ADD r2,r2,#1 //等于零则进行赋值 +FZETestInc: + STREX R3, R2, [R0] + CMP R3, #1 //检查 STREX 是否被驳回 + + BEQ TryTestInc //重新尝试 + MOV R0,R4 + pop {r4} + bx lr + +.global atomic_test_dec_nq +.section .text.atomic_test_dec_nq +.type atomic_test_dec_nq, %function +atomic_test_dec_nq: + push {r4} +TryTestDecNq: + LDREX r2, [R0] + CMP R2,#0 //比较是否等于0 + BEQ FZTestDecNq//等于0则跳转 + MOV R4,#0 + ADD r2, #-1 //不等于零则减一 + B FZETestDecNq +FZTestDecNq: + MOV R4,#1 +FZETestDecNq: + STREX R3, R2, [R0] + CMP R3, #1 //检查 STREX 是否被驳回 + + BEQ TryTestDecNq //重新尝试 + MOV R0,R4 + pop {r4} + bx lr + +//b<=a a+=1 +.global atomic_cmp_hi_inc +.section .text.atomic_cmp_hi_inc +.type atomic_cmp_hi_inc, %function +atomic_cmp_hi_add: + push {r4} +atomic_cmp_hi_add_: + LDREX r2, [r0] + cmp r1,r2 //b,a + bls atomic_cmp_hi_add_nx_ + MOV r4,#0 +atomic_cmp_hi_add_nx_: + ADD r2,r2,#1 + MOV r4,#1 + STREX r3,r2,[r0] + CMP R3, #1 + BEQ atomic_cmp_hi_add_ + MOV R0,R4 + pop {r4} + bx lr + +//a<=b a+=1 +.global atomic_cmp_hi_inc1 +.section .text.atomic_cmp_hi_inc1 +.type atomic_cmp_hi_inc1, %function +atomic_cmp_hi_add1: + push {r4} +atomic_cmp_hi_add1_: + ldrex r2,[r0] + cmp r2,r1 + bls atomic_cmp_hi_add1_nx_ + MOV r4,#0 +atomic_cmp_hi_add1_nx_: + ADD r2,r2,#1 + MOV r4,#1 + STREX r3,r2,[r0] + CMP R3, #1 + BEQ atomic_cmp_hi_add1_ + MOV R0,R4 + pop {r4} + bx lr + diff --git a/mkrtos_knl/arch/cortex-m33/core_it.c b/mkrtos_knl/arch/cortex-m33/core_it.c new file mode 100755 index 000000000..9c1155052 --- /dev/null +++ b/mkrtos_knl/arch/cortex-m33/core_it.c @@ -0,0 +1,220 @@ +/** + ****************************************************************************** + * @file Project/STM32F2xx_StdPeriph_Template/stm32f2xx_it.c + * @author MCD Application Team + * @version V1.1.0 + * @date 13-April-2012 + * @brief Main Interrupt Service Routines. + * This file provides template for all exceptions handler and + * peripherals interrupt service routine. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "mk_sys.h" +#include "printk.h" +#include "mm_man.h" +#include "task.h" +#include "thread.h" +#include "map.h" +#include "thread_knl.h" +/** @addtogroup Template_Project + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/******************************************************************************/ +/* Cortex-M3 Processor Exceptions Handlers */ +/******************************************************************************/ + +/** + * @brief This function handles NMI exception. + * @param None + * @retval None + */ +void NMI_Handler(void) +{ + printk("%s\n", __FUNCTION__); +} + +/** + * @brief This function handles Hard Fault exception. + * @param None + * @retval None + */ +void HardFault_Handler(void) +{ + bool_t is_knl = is_run_knl(); + + printk("%s\n", __FUNCTION__); + task_knl_kill(thread_get_current(), is_knl); +} + +/** + * @brief This function handles Memory Manage exception. + * @param None + * @retval None + */ +void MemManage_Handler(void) +{ + bool_t is_knl = is_run_knl(); + addr_t fault_addr = (addr_t)(SCB->MMFAR); + task_t *cur_task = thread_get_current_task(); + umword_t status; + + // printk("%s\n", __FUNCTION__); + if (SCB->CFSR & 0x1) + { + printk("instr 0x%x access is error.\n", fault_addr); + } + if (SCB->CFSR & 2) + { + printk("data 0x%x access is error.\n", fault_addr); + } + if (SCB->CFSR & 128) + { + fault_addr = (addr_t)(SCB->MMFAR); + // if (mm_page_alloc_fault(&cur_task->mm_space.mm_pages, fault_addr) == NULL) + // { + // goto end; + // } + // return; + goto end; + } + if ((SCB->CFSR & 8)) + { + printk("出栈错误\n"); + // fault_addr = arch_get_user_sp(); + + // if (mm_page_alloc_fault(&cur_task->mm_space.mm_pages, fault_addr) == NULL) + // { + // goto end; + // } + // return; + goto end; + } + if (SCB->CFSR & 16) + { + printk("压栈错误\n"); + // fault_addr = arch_get_user_sp(); + + // if (mm_page_alloc_fault(&cur_task->mm_space.mm_pages, fault_addr) == NULL) + // { + // goto end; + // } + // return; + goto end; + } + if (SCB->CFSR & 32) + { + printk("浮点惰性压栈错误\n"); + } + +end: + printk("task:0x%x, semgement fault.\n", thread_get_current_task()); + task_knl_kill(thread_get_current(), is_knl); +} + +/** + * @brief This function handles Bus Fault exception. + * @param None + * @retval None + */ +void BusFault_Handler(void) +{ + bool_t is_knl = is_run_knl(); + + printk("%s\n", __FUNCTION__); + task_knl_kill(thread_get_current(), is_knl); +} + +/** + * @brief This function handles Usage Fault exception. + * @param None + * @retval None + */ +void UsageFault_Handler(void) +{ + bool_t is_knl = is_run_knl(); + printk("%s\n", __FUNCTION__); + if (SCB->CFSR & (1 << 16)) + { + printk("Undefined instruction error\n"); + } + if (SCB->CFSR & (1 << 17)) + { + printk("Trying to switch to the wrong state\n"); + } + if (SCB->CFSR & (1 << 18)) + { + printk("An exception attempting to execute an EXC_RETURN error\n"); + } + if (SCB->CFSR & (1 << 19)) + { + printk("An attempt was made to execute a coprocessor instruction\n"); + } + if (SCB->CFSR & (1 << 24)) + { + printk("A non-access error was generated\n"); + } + if (SCB->CFSR & (1 << 25)) + { + printk("Division by zero error\n"); + } + task_knl_kill(thread_get_current(), is_knl); +} + +/** + * @brief This function handles Debug Monitor exception. + * @param None + * @retval None + */ +void DebugMon_Handler(void) +{ + printk("%s\n", __FUNCTION__); +} + +/******************************************************************************/ +/* STM32F2xx Peripherals Interrupt Handlers */ +/* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */ +/* available peripheral interrupt handler's name please refer to the startup */ +/* file (startup_stm32f2xx.s). */ +/******************************************************************************/ + +/** + * @brief This function handles PPP interrupt request. + * @param None + * @retval None + */ +/*void PPP_IRQHandler(void) +{ +}*/ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/mkrtos_knl/arch/cortex-m33/link.lds b/mkrtos_knl/arch/cortex-m33/link.lds new file mode 100644 index 000000000..5985df8f7 --- /dev/null +++ b/mkrtos_knl/arch/cortex-m33/link.lds @@ -0,0 +1,86 @@ +ENTRY(Reset_Handler) +MEMORY +{ + RAM (arw) : ORIGIN = 0x20000000, LENGTH = 0x800000 + FLASH (arx) : ORIGIN = 0x8000000 + 0x2000, LENGTH = 0x10000 - 0x2000 +} +SECTIONS +{ + . = ORIGIN(FLASH); + .text : + { + KEEP(*(.isr_vector)) + *(.text) + *(.text*) + *(.rodata*) + } > FLASH + .text : + { + . = ALIGN(4); + *(.text) + *(.text*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + KEEP (*(.init)) + KEEP (*(.fini)) + . = ALIGN(4); + _etext = .; + } >FLASH + .rodata : + { + . = ALIGN(4); + *(.rodata) + *(.rodata*) + . = ALIGN(4); + } >FLASH + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + _sidata = LOADADDR(.data); + .data : + { + . = ALIGN(4); + _sdata = .; + *(.data) + *(.data*) + . = ALIGN(4); + _edata = .; + } >RAM AT> FLASH + . = ALIGN(4); + .bss : + { + _sbss = .; + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + . = ALIGN(4); + _ebss = .; + __bss_end__ = _ebss; + } >RAM + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/mkrtos_knl/arch/cortex-m33/link.lds.S b/mkrtos_knl/arch/cortex-m33/link.lds.S new file mode 100644 index 000000000..860eded91 --- /dev/null +++ b/mkrtos_knl/arch/cortex-m33/link.lds.S @@ -0,0 +1,115 @@ + + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Specify the memory areas */ +MEMORY +{ + RAM (arw) : ORIGIN = CONFIG_KNL_DATA_ADDR, LENGTH = CONFIG_KNL_DATA_SIZE + FLASH (arx) : ORIGIN = CONFIG_KNL_TEXT_ADDR + CONFIG_KNL_OFFSET, LENGTH = CONFIG_INIT_TASK_OFFSET - CONFIG_KNL_OFFSET +} + +/* Define output sections */ +SECTIONS +{ + . = ORIGIN(FLASH); + .text : + { + KEEP(*(.isr_vector)) + + *(.text) + *(.text*) + *(.rodata*) + } > FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + + } >FLASH + + /* Constant data goes into FLASH */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >RAM AT> FLASH + + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + .ARM.attributes 0 : { *(.ARM.attributes) } +} + + diff --git a/mkrtos_knl/arch/cortex-m33/sche.S b/mkrtos_knl/arch/cortex-m33/sche.S new file mode 100755 index 000000000..2b89ce385 --- /dev/null +++ b/mkrtos_knl/arch/cortex-m33/sche.S @@ -0,0 +1,92 @@ +.syntax unified +@ .cpu cortex-m3 +.thumb + +.global mpu_switch_to +.global sched_reset + +.global PendSV_Handler +.type PendSV_Handler, %function +PendSV_Handler: + CPSID I + + // psp和msp作为任务切换的参数 + MRS R0,PSP + MRS R1,MSP + + // 如果不是第一次调度了,则保存r4-r11到栈内 + TST LR,#4 + ITE EQ + MRSEQ r3, MSP + MRSNE r3, PSP + mov r2, lr + + push {r4} + ldr r4, =sched_reset + ldr r4, [r4] + //! psp为零时,立刻调度一次 + CBZ r4, thread_sche + pop {r4} + SUB R3, R3, #0x20 //R3 -= 32 + STM R3, {R4-R11} + + //将更改的值放回要传的参数中去 + TST LR,#4 + ITTEE EQ + MSREQ MSP, r3 + MOVEQ r1,r3 + MSRNE PSP, r3 + MOVNE r0,r3 + b thread_sche_next +thread_sche: + pop {r4} +thread_sche_next: + // r0:psp r1:msp r2:(0为msp 1 psp) + LDR.w r3,=schde_to + BLX r3 + //取得下一个任务的参数 r1 psp r2 msp + lDRD r1,r2,[r0] + //用户使用的栈类型r3 0为msp 1为ps + LDR r3,[R0,#8] + + TST r3,#4 //检测使用的寄存器 + ITE EQ + MOVEQ R0,R2 + MOVNE R0,R1 //不等于零则使用psp + LDM r0, {R4-R11} //恢复新的r4-r11的值 + ADDS r0, r0, #0x20 //R0 += 0x20 + + //保存栈的值回去 + MSR MSP,R2 + MSR PSP,R1 + + //等于一跳转到用户模式 + @ CMP r3,#1 + TST r3,#4 //检测使用的寄存器 + IT EQ + BEQ super_mode//psp模式则跳转 + B user_mode +user_mode: +//psp模式则保存 + MSR PSP, r0 + //切换到用户线程模式 + MOV R1,#1 + MSR CONTROL, R1 + //lr 的第2位为1时自动切换到PSP + MOV LR,r3 + B to_ret + +super_mode: //更新下msp的值 + MSR MSP,R0 + MOV LR,r3 + //内核线程,设置为特权模式 + MOV R0,#0 + MSR CONTROL, R0 +to_ret: + push {r0-r3, lr} + bl mpu_switch_to + pop {r0-r3, lr} + CPSIE I + DSB + ISB + BX LR diff --git a/mkrtos_knl/arch/armv7m/swm34s/CMakeLists.txt b/mkrtos_knl/arch/cortex-m33/swm34s/CMakeLists.txt similarity index 100% rename from mkrtos_knl/arch/armv7m/swm34s/CMakeLists.txt rename to mkrtos_knl/arch/cortex-m33/swm34s/CMakeLists.txt diff --git a/mkrtos_knl/arch/armv7m/swm34s/arch.c b/mkrtos_knl/arch/cortex-m33/swm34s/arch.c similarity index 100% rename from mkrtos_knl/arch/armv7m/swm34s/arch.c rename to mkrtos_knl/arch/cortex-m33/swm34s/arch.c diff --git a/mkrtos_knl/arch/armv7m/swm34s/arch.h b/mkrtos_knl/arch/cortex-m33/swm34s/arch.h similarity index 100% rename from mkrtos_knl/arch/armv7m/swm34s/arch.h rename to mkrtos_knl/arch/cortex-m33/swm34s/arch.h diff --git a/mkrtos_knl/arch/armv7m/swm34s/armv8m_mpu.h b/mkrtos_knl/arch/cortex-m33/swm34s/armv8m_mpu.h similarity index 100% rename from mkrtos_knl/arch/armv7m/swm34s/armv8m_mpu.h rename to mkrtos_knl/arch/cortex-m33/swm34s/armv8m_mpu.h diff --git a/mkrtos_knl/arch/armv7m/swm34s/mk_sys.h b/mkrtos_knl/arch/cortex-m33/swm34s/mk_sys.h similarity index 100% rename from mkrtos_knl/arch/armv7m/swm34s/mk_sys.h rename to mkrtos_knl/arch/cortex-m33/swm34s/mk_sys.h diff --git a/mkrtos_knl/arch/armv7m/swm34s/mpu.c b/mkrtos_knl/arch/cortex-m33/swm34s/mpu.c similarity index 100% rename from mkrtos_knl/arch/armv7m/swm34s/mpu.c rename to mkrtos_knl/arch/cortex-m33/swm34s/mpu.c diff --git a/mkrtos_knl/arch/armv7m/swm34s/startup_SWM341.s b/mkrtos_knl/arch/cortex-m33/swm34s/startup_SWM341.s similarity index 100% rename from mkrtos_knl/arch/armv7m/swm34s/startup_SWM341.s rename to mkrtos_knl/arch/cortex-m33/swm34s/startup_SWM341.s diff --git a/mkrtos_knl/arch/armv7m/swm34s/system_SWM341.c b/mkrtos_knl/arch/cortex-m33/swm34s/system_SWM341.c similarity index 100% rename from mkrtos_knl/arch/armv7m/swm34s/system_SWM341.c rename to mkrtos_knl/arch/cortex-m33/swm34s/system_SWM341.c diff --git a/mkrtos_knl/arch/armv7m/swm34s/system_SWM341.h b/mkrtos_knl/arch/cortex-m33/swm34s/system_SWM341.h similarity index 100% rename from mkrtos_knl/arch/armv7m/swm34s/system_SWM341.h rename to mkrtos_knl/arch/cortex-m33/swm34s/system_SWM341.h diff --git a/mkrtos_knl/arch/cortex-m33/syscall.S b/mkrtos_knl/arch/cortex-m33/syscall.S new file mode 100755 index 000000000..b9a8e3cc6 --- /dev/null +++ b/mkrtos_knl/arch/cortex-m33/syscall.S @@ -0,0 +1,109 @@ +.syntax unified +@ .cpu cortex-m3 +.thumb + +.global syscall_handler_get +/** +* @brief syscall结束时到这儿 +*/ +.type syscall_exit, %function +syscall_exit: + svc 1 + b . + +/** +* void syscall_ret_user(int ret_val); +* @brief 回到用户模式 +*/ +.type syscall_ret_user, %function +syscall_ret_user: + //存放返回值 + + //还原msp的值 + mrs r0, msp + add r0, #0x20 + ldmfd r0!,{r4-r11} + msr msp,r0 + pop {r0,r1,r2,lr} + + msr CONTROL, r1 + CPSIE I + bx lr + +/** +* void SVC_Handler(void); +* @brief +*/ +.global SVC_Handler +.type SVC_Handler, %function +SVC_Handler: +CPSID I + TST.W LR, #4 + ITE EQ + MRSEQ R1, MSP + MRSNE R1, PSP + //获得svc的调用号 + LDR R2, [R1, #24] + LDRB R2, [R2, #-2] + + cmp r2,#128 + beq SYS_CALL + cmp r2,#1 + beq TO_USER + cmp r2,#2 +// beq enter_fchannel +// cmp r2,#3 +// beq exit_fchannel + b TO_END +TO_USER: + B syscall_ret_user + +SYS_CALL: + //获取堆栈地址 + mov r0,r1 + //放入之前的栈地址 + mrs r1,CONTROL + + push {r0,r1,r2,lr} + //svc 128 + mov r1, r7 + //获得需要调用的syscall函数的地址 + push {r0-r2,lr} + blx syscall_handler_get + mov r3,r0 + pop {r0-r2,lr} + + //r4-r11 压入到内核栈中 + stmfd sp!,{r4-r11} + //压入到用户栈中 + stmfd r0,{r4-r11} + //取出PSR PC LR R12 R3 R2 R1 R0 + ldmfd r0,{r4-r11} + //压入到内核栈中 + stmfd sp!,{r4-r11} + + //取出lr与pc放到栈中 + mov r0,sp + ldr r2, =syscall_exit + //lr + str r2, [r0, #20] + //pc + str r3, [r0, #24] + ldr r3, =0x01000000 + str r3, [r0, #28] + + //重新设置control + mrs r0, CONTROL + bic r0, r0, #0x03 + msr CONTROL, r0 + + dsb + isb + orr lr, lr, #0x18 + bic lr, lr, #0x04 + CPSIE I + bx lr + +TO_END: +CPSIE I + bx lr diff --git a/mkrtos_knl/arch/cortex-m4/CMakeLists.txt b/mkrtos_knl/arch/cortex-m4/CMakeLists.txt new file mode 100755 index 000000000..daf32cba9 --- /dev/null +++ b/mkrtos_knl/arch/cortex-m4/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 3.13) + +file(GLOB deps *.c *.S) + +add_library(arch STATIC ${deps}) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D__MPU_PRESENT=1 -DUSE_STDPERIPH_DRIVER=1 ") +message(=======${CONFIG_CPU_TYPE}) + +if (${CONFIG_CPU_TYPE} STREQUAL "stm32f4" ) + if(${BOARD} STREQUAL "STM32F407VET6" ) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DSTM32F40_41xxx ") + endif() + target_include_directories( + arch + PUBLIC + ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/${ARCH}/${CONFIG_CPU_TYPE} + ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/knl + + ${CMAKE_SOURCE_DIR}/mkrtos_bsp/STM32/STM32F4xx_DSP_StdPeriph_Lib_V1.9.0/Libraries/STM32F4xx_StdPeriph_Driver/inc + ) + add_subdirectory(${CONFIG_CPU_TYPE}) +endif() + +target_link_libraries( + arch + PUBLIC + knl_bsp +) +target_include_directories( + arch + PUBLIC + ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/inc + ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/lib + ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/knl +) diff --git a/mkrtos_knl/arch/cortex-m4/atomic.S b/mkrtos_knl/arch/cortex-m4/atomic.S new file mode 100644 index 000000000..da2369a39 --- /dev/null +++ b/mkrtos_knl/arch/cortex-m4/atomic.S @@ -0,0 +1,287 @@ +.syntax unified +@ .cpu cortex-m3 +.thumb + +.global atomic_inc +.section .text.atomic_inc +.type atomic_inc, %function +atomic_inc: + MOV R3,#0 + TryInc: + LDREX r2, [R0] + ADD r2, #1 + CMP R2,#0 + BEQ incN + B incN1 + incN: + MOV R3,#1 + incN1: + STREX R1, R2, [R0] + CMP R1, #1 //检查 STREX 是否被驳回 + BEQ TryInc //重新尝试 + MOV R0,R3 + bx lr + +.global atomic_dec +.section .text.atomic_dec +.type atomic_dec, %function +atomic_dec: + MOV R3,#0 + TryDec: + LDREX r2, [R0] + ADD r2, #-1 + CMP R2,#0 + BEQ decN + B decN1 + decN: + MOV R3,#1 + decN1: + STREX R1, R2, [R0] + CMP R1, #1 //检查 STREX 是否被驳回 + + BEQ TryDec //重新尝试 + + bx lr +.global atomic_set +.section .text.atomic_set +.type atomic_set, %function +atomic_set: +TrySet: + LDREX r2, [R0] + MOV r2, R1 + STREX R3, R2, [R0] + CMP R3, #1 //检查 STREX 是否被驳回 + BEQ TrySet //重新尝试 + + bx lr + +.global atomic_ret_set +.section .text.atomic_ret_set +.type atomic_ret_set, %function +atomic_ret_set: + push {r4} +TryRetSet: + LDREX r2, [R0] + mov r4,r2 + MOV r2, R1 + STREX R3, R2, [R0] + CMP R3, #1 //检查 STREX 是否被驳回 + BEQ TryRetSet //重新尝试 + mov r0,r4 + pop {r4} + bx lr + +.global atomic_read +.section .text.atomic_read +.type atomic_read, %function +atomic_read: + LDR R0, [R0] + BX LR + +.global atomic_add +.section .text.atomic_add +.type atomic_add, %function +atomic_add: + MOV R3,R1 +TryAdd: + LDREX r2, [R0] + ADD r2, R3 + STREX R1, R2, [R0] + CMP R1, #1 //检查 STREX 是否被驳回 + BEQ TryAdd //重新尝试 + BX LR + +.global atomic_sub +.section .text.atomic_sub +.type atomic_sub, %function +atomic_sub: + MOV R3,R1 +TrySub: + LDREX r2, [R0] + SUB r2, R3 + STREX R1, R2, [R0] + CMP R1, #1 //检查 STREX 是否被驳回 + BEQ TrySub //重新尝试 + BX LR + +.global atomic_test +.section .text.atomic_test +.type atomic_test, %function +atomic_test: + push {r4} +TryTest: + LDREX r2, [R0] + CMP R2,r1 //比较是否等于 + BEQ FZTest //等于则跳转到赋值 + MOV R4,#0 + B FZETest +FZTest: + MOV R4,#1 +FZETest: + STREX R3, R2, [R0] + CMP R3, #1 //检查 STREX 是否被驳回 + + BEQ TryTest //重新尝试 + MOV R0,R4 + pop {r4} + bx lr + +.global atomic_test_set +.section .text.atomic_test_set +.type atomic_test_set, %function +atomic_test_set: + push {r4} +TryTestSet: + LDREX r2, [R0] + CMP R2,#0 //比较是否等于0 + BEQ FZTestSet //等于0则跳转到赋值 + MOV R4,#0 + B FZETestSet +FZTestSet: + MOV R4,#1 + MOV r2, R1 //等于零则进行赋值 +FZETestSet: + STREX R3, R2, [R0] + CMP R3, #1 //检查 STREX 是否被驳回 + + BEQ TryTestSet //重新尝试 + MOV R0,R4 + pop {r4} + bx lr + +.global atomic_set_test +.section .text.atomic_set_test +.type atomic_set_test, %function +atomic_set_test: + push {r4} +TrySetTest: + LDREX r2, [R0] + CMP R2,#0 //比较是否等于0 + BEQ FZSetTest //等于0则跳转到赋值 + MOV R4,#0 + B FZESetTest +FZSetTest: + MOV R4,#1 + +FZESetTest: + MOV r2, R1 //等于零则进行赋值 + STREX R3, R2, [R0] + CMP R3, #1 //检查 STREX 是否被驳回 + + BEQ TrySetTest //重新尝试 + MOV R0,R4 + pop {r4} + bx lr + +.global atomic_inc_test +.section .text.atomic_inc_test +.type atomic_inc_test, %function +atomic_inc_test: + push {r4} + TryIncTest: + LDREX r2, [R0] + CMP R2,#0 //比较是否等于0 + BEQ FZIncTest //等于0则跳转到赋值 + MOV R4,#0 + B FZEIncTest + FZIncTest: + MOV R4,#1 + FZEIncTest: + ADD R2,R2,#1 + STREX R3, R2, [R0] + CMP R3, #1 //检查 STREX 是否被驳回 + + BEQ TryIncTest //重新尝试 + MOV R0,R4 + pop {r4} + bx lr + + +.global atomic_test_inc +.section .text.atomic_test_inc +.type atomic_test_inc, %function +atomic_test_inc: + push {r4} +TryTestInc: + LDREX r2, [R0] + CMP R2,#0 //比较是否等于0 + BEQ FZTestInc //等于0则跳转到赋值 + MOV R4,#0 + B FZETestInc +FZTestInc: + MOV R4,#1 + ADD r2,r2,#1 //等于零则进行赋值 +FZETestInc: + STREX R3, R2, [R0] + CMP R3, #1 //检查 STREX 是否被驳回 + + BEQ TryTestInc //重新尝试 + MOV R0,R4 + pop {r4} + bx lr + +.global atomic_test_dec_nq +.section .text.atomic_test_dec_nq +.type atomic_test_dec_nq, %function +atomic_test_dec_nq: + push {r4} +TryTestDecNq: + LDREX r2, [R0] + CMP R2,#0 //比较是否等于0 + BEQ FZTestDecNq//等于0则跳转 + MOV R4,#0 + ADD r2, #-1 //不等于零则减一 + B FZETestDecNq +FZTestDecNq: + MOV R4,#1 +FZETestDecNq: + STREX R3, R2, [R0] + CMP R3, #1 //检查 STREX 是否被驳回 + + BEQ TryTestDecNq //重新尝试 + MOV R0,R4 + pop {r4} + bx lr + +//b<=a a+=1 +.global atomic_cmp_hi_inc +.section .text.atomic_cmp_hi_inc +.type atomic_cmp_hi_inc, %function +atomic_cmp_hi_add: + push {r4} +atomic_cmp_hi_add_: + LDREX r2, [r0] + cmp r1,r2 //b,a + bls atomic_cmp_hi_add_nx_ + MOV r4,#0 +atomic_cmp_hi_add_nx_: + ADD r2,r2,#1 + MOV r4,#1 + STREX r3,r2,[r0] + CMP R3, #1 + BEQ atomic_cmp_hi_add_ + MOV R0,R4 + pop {r4} + bx lr + +//a<=b a+=1 +.global atomic_cmp_hi_inc1 +.section .text.atomic_cmp_hi_inc1 +.type atomic_cmp_hi_inc1, %function +atomic_cmp_hi_add1: + push {r4} +atomic_cmp_hi_add1_: + ldrex r2,[r0] + cmp r2,r1 + bls atomic_cmp_hi_add1_nx_ + MOV r4,#0 +atomic_cmp_hi_add1_nx_: + ADD r2,r2,#1 + MOV r4,#1 + STREX r3,r2,[r0] + CMP R3, #1 + BEQ atomic_cmp_hi_add1_ + MOV R0,R4 + pop {r4} + bx lr + diff --git a/mkrtos_knl/arch/cortex-m4/core_it.c b/mkrtos_knl/arch/cortex-m4/core_it.c new file mode 100755 index 000000000..9c1155052 --- /dev/null +++ b/mkrtos_knl/arch/cortex-m4/core_it.c @@ -0,0 +1,220 @@ +/** + ****************************************************************************** + * @file Project/STM32F2xx_StdPeriph_Template/stm32f2xx_it.c + * @author MCD Application Team + * @version V1.1.0 + * @date 13-April-2012 + * @brief Main Interrupt Service Routines. + * This file provides template for all exceptions handler and + * peripherals interrupt service routine. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "mk_sys.h" +#include "printk.h" +#include "mm_man.h" +#include "task.h" +#include "thread.h" +#include "map.h" +#include "thread_knl.h" +/** @addtogroup Template_Project + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/******************************************************************************/ +/* Cortex-M3 Processor Exceptions Handlers */ +/******************************************************************************/ + +/** + * @brief This function handles NMI exception. + * @param None + * @retval None + */ +void NMI_Handler(void) +{ + printk("%s\n", __FUNCTION__); +} + +/** + * @brief This function handles Hard Fault exception. + * @param None + * @retval None + */ +void HardFault_Handler(void) +{ + bool_t is_knl = is_run_knl(); + + printk("%s\n", __FUNCTION__); + task_knl_kill(thread_get_current(), is_knl); +} + +/** + * @brief This function handles Memory Manage exception. + * @param None + * @retval None + */ +void MemManage_Handler(void) +{ + bool_t is_knl = is_run_knl(); + addr_t fault_addr = (addr_t)(SCB->MMFAR); + task_t *cur_task = thread_get_current_task(); + umword_t status; + + // printk("%s\n", __FUNCTION__); + if (SCB->CFSR & 0x1) + { + printk("instr 0x%x access is error.\n", fault_addr); + } + if (SCB->CFSR & 2) + { + printk("data 0x%x access is error.\n", fault_addr); + } + if (SCB->CFSR & 128) + { + fault_addr = (addr_t)(SCB->MMFAR); + // if (mm_page_alloc_fault(&cur_task->mm_space.mm_pages, fault_addr) == NULL) + // { + // goto end; + // } + // return; + goto end; + } + if ((SCB->CFSR & 8)) + { + printk("出栈错误\n"); + // fault_addr = arch_get_user_sp(); + + // if (mm_page_alloc_fault(&cur_task->mm_space.mm_pages, fault_addr) == NULL) + // { + // goto end; + // } + // return; + goto end; + } + if (SCB->CFSR & 16) + { + printk("压栈错误\n"); + // fault_addr = arch_get_user_sp(); + + // if (mm_page_alloc_fault(&cur_task->mm_space.mm_pages, fault_addr) == NULL) + // { + // goto end; + // } + // return; + goto end; + } + if (SCB->CFSR & 32) + { + printk("浮点惰性压栈错误\n"); + } + +end: + printk("task:0x%x, semgement fault.\n", thread_get_current_task()); + task_knl_kill(thread_get_current(), is_knl); +} + +/** + * @brief This function handles Bus Fault exception. + * @param None + * @retval None + */ +void BusFault_Handler(void) +{ + bool_t is_knl = is_run_knl(); + + printk("%s\n", __FUNCTION__); + task_knl_kill(thread_get_current(), is_knl); +} + +/** + * @brief This function handles Usage Fault exception. + * @param None + * @retval None + */ +void UsageFault_Handler(void) +{ + bool_t is_knl = is_run_knl(); + printk("%s\n", __FUNCTION__); + if (SCB->CFSR & (1 << 16)) + { + printk("Undefined instruction error\n"); + } + if (SCB->CFSR & (1 << 17)) + { + printk("Trying to switch to the wrong state\n"); + } + if (SCB->CFSR & (1 << 18)) + { + printk("An exception attempting to execute an EXC_RETURN error\n"); + } + if (SCB->CFSR & (1 << 19)) + { + printk("An attempt was made to execute a coprocessor instruction\n"); + } + if (SCB->CFSR & (1 << 24)) + { + printk("A non-access error was generated\n"); + } + if (SCB->CFSR & (1 << 25)) + { + printk("Division by zero error\n"); + } + task_knl_kill(thread_get_current(), is_knl); +} + +/** + * @brief This function handles Debug Monitor exception. + * @param None + * @retval None + */ +void DebugMon_Handler(void) +{ + printk("%s\n", __FUNCTION__); +} + +/******************************************************************************/ +/* STM32F2xx Peripherals Interrupt Handlers */ +/* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */ +/* available peripheral interrupt handler's name please refer to the startup */ +/* file (startup_stm32f2xx.s). */ +/******************************************************************************/ + +/** + * @brief This function handles PPP interrupt request. + * @param None + * @retval None + */ +/*void PPP_IRQHandler(void) +{ +}*/ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/mkrtos_knl/arch/cortex-m4/link.lds b/mkrtos_knl/arch/cortex-m4/link.lds new file mode 100644 index 000000000..5985df8f7 --- /dev/null +++ b/mkrtos_knl/arch/cortex-m4/link.lds @@ -0,0 +1,86 @@ +ENTRY(Reset_Handler) +MEMORY +{ + RAM (arw) : ORIGIN = 0x20000000, LENGTH = 0x800000 + FLASH (arx) : ORIGIN = 0x8000000 + 0x2000, LENGTH = 0x10000 - 0x2000 +} +SECTIONS +{ + . = ORIGIN(FLASH); + .text : + { + KEEP(*(.isr_vector)) + *(.text) + *(.text*) + *(.rodata*) + } > FLASH + .text : + { + . = ALIGN(4); + *(.text) + *(.text*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + KEEP (*(.init)) + KEEP (*(.fini)) + . = ALIGN(4); + _etext = .; + } >FLASH + .rodata : + { + . = ALIGN(4); + *(.rodata) + *(.rodata*) + . = ALIGN(4); + } >FLASH + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + _sidata = LOADADDR(.data); + .data : + { + . = ALIGN(4); + _sdata = .; + *(.data) + *(.data*) + . = ALIGN(4); + _edata = .; + } >RAM AT> FLASH + . = ALIGN(4); + .bss : + { + _sbss = .; + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + . = ALIGN(4); + _ebss = .; + __bss_end__ = _ebss; + } >RAM + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/mkrtos_knl/arch/cortex-m4/link.lds.S b/mkrtos_knl/arch/cortex-m4/link.lds.S new file mode 100644 index 000000000..860eded91 --- /dev/null +++ b/mkrtos_knl/arch/cortex-m4/link.lds.S @@ -0,0 +1,115 @@ + + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Specify the memory areas */ +MEMORY +{ + RAM (arw) : ORIGIN = CONFIG_KNL_DATA_ADDR, LENGTH = CONFIG_KNL_DATA_SIZE + FLASH (arx) : ORIGIN = CONFIG_KNL_TEXT_ADDR + CONFIG_KNL_OFFSET, LENGTH = CONFIG_INIT_TASK_OFFSET - CONFIG_KNL_OFFSET +} + +/* Define output sections */ +SECTIONS +{ + . = ORIGIN(FLASH); + .text : + { + KEEP(*(.isr_vector)) + + *(.text) + *(.text*) + *(.rodata*) + } > FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + + } >FLASH + + /* Constant data goes into FLASH */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >RAM AT> FLASH + + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + .ARM.attributes 0 : { *(.ARM.attributes) } +} + + diff --git a/mkrtos_knl/arch/cortex-m4/sche.S b/mkrtos_knl/arch/cortex-m4/sche.S new file mode 100755 index 000000000..2b89ce385 --- /dev/null +++ b/mkrtos_knl/arch/cortex-m4/sche.S @@ -0,0 +1,92 @@ +.syntax unified +@ .cpu cortex-m3 +.thumb + +.global mpu_switch_to +.global sched_reset + +.global PendSV_Handler +.type PendSV_Handler, %function +PendSV_Handler: + CPSID I + + // psp和msp作为任务切换的参数 + MRS R0,PSP + MRS R1,MSP + + // 如果不是第一次调度了,则保存r4-r11到栈内 + TST LR,#4 + ITE EQ + MRSEQ r3, MSP + MRSNE r3, PSP + mov r2, lr + + push {r4} + ldr r4, =sched_reset + ldr r4, [r4] + //! psp为零时,立刻调度一次 + CBZ r4, thread_sche + pop {r4} + SUB R3, R3, #0x20 //R3 -= 32 + STM R3, {R4-R11} + + //将更改的值放回要传的参数中去 + TST LR,#4 + ITTEE EQ + MSREQ MSP, r3 + MOVEQ r1,r3 + MSRNE PSP, r3 + MOVNE r0,r3 + b thread_sche_next +thread_sche: + pop {r4} +thread_sche_next: + // r0:psp r1:msp r2:(0为msp 1 psp) + LDR.w r3,=schde_to + BLX r3 + //取得下一个任务的参数 r1 psp r2 msp + lDRD r1,r2,[r0] + //用户使用的栈类型r3 0为msp 1为ps + LDR r3,[R0,#8] + + TST r3,#4 //检测使用的寄存器 + ITE EQ + MOVEQ R0,R2 + MOVNE R0,R1 //不等于零则使用psp + LDM r0, {R4-R11} //恢复新的r4-r11的值 + ADDS r0, r0, #0x20 //R0 += 0x20 + + //保存栈的值回去 + MSR MSP,R2 + MSR PSP,R1 + + //等于一跳转到用户模式 + @ CMP r3,#1 + TST r3,#4 //检测使用的寄存器 + IT EQ + BEQ super_mode//psp模式则跳转 + B user_mode +user_mode: +//psp模式则保存 + MSR PSP, r0 + //切换到用户线程模式 + MOV R1,#1 + MSR CONTROL, R1 + //lr 的第2位为1时自动切换到PSP + MOV LR,r3 + B to_ret + +super_mode: //更新下msp的值 + MSR MSP,R0 + MOV LR,r3 + //内核线程,设置为特权模式 + MOV R0,#0 + MSR CONTROL, R0 +to_ret: + push {r0-r3, lr} + bl mpu_switch_to + pop {r0-r3, lr} + CPSIE I + DSB + ISB + BX LR diff --git a/mkrtos_knl/arch/armv7m/stm32f4/CMakeLists.txt b/mkrtos_knl/arch/cortex-m4/stm32f4/CMakeLists.txt similarity index 100% rename from mkrtos_knl/arch/armv7m/stm32f4/CMakeLists.txt rename to mkrtos_knl/arch/cortex-m4/stm32f4/CMakeLists.txt diff --git a/mkrtos_knl/arch/armv7m/stm32f4/arch.c b/mkrtos_knl/arch/cortex-m4/stm32f4/arch.c similarity index 100% rename from mkrtos_knl/arch/armv7m/stm32f4/arch.c rename to mkrtos_knl/arch/cortex-m4/stm32f4/arch.c diff --git a/mkrtos_knl/arch/armv7m/stm32f4/arch.h b/mkrtos_knl/arch/cortex-m4/stm32f4/arch.h similarity index 100% rename from mkrtos_knl/arch/armv7m/stm32f4/arch.h rename to mkrtos_knl/arch/cortex-m4/stm32f4/arch.h diff --git a/mkrtos_knl/arch/armv7m/stm32f4/mk_sys.h b/mkrtos_knl/arch/cortex-m4/stm32f4/mk_sys.h similarity index 100% rename from mkrtos_knl/arch/armv7m/stm32f4/mk_sys.h rename to mkrtos_knl/arch/cortex-m4/stm32f4/mk_sys.h diff --git a/mkrtos_knl/arch/armv7m/stm32f4/mpu.c b/mkrtos_knl/arch/cortex-m4/stm32f4/mpu.c similarity index 100% rename from mkrtos_knl/arch/armv7m/stm32f4/mpu.c rename to mkrtos_knl/arch/cortex-m4/stm32f4/mpu.c diff --git a/mkrtos_knl/arch/armv7m/stm32f4/startup_stm32f40xx.s b/mkrtos_knl/arch/cortex-m4/stm32f4/startup_stm32f40xx.s similarity index 100% rename from mkrtos_knl/arch/armv7m/stm32f4/startup_stm32f40xx.s rename to mkrtos_knl/arch/cortex-m4/stm32f4/startup_stm32f40xx.s diff --git a/mkrtos_knl/arch/armv7m/stm32f4/stm32f4xx_conf.h b/mkrtos_knl/arch/cortex-m4/stm32f4/stm32f4xx_conf.h similarity index 100% rename from mkrtos_knl/arch/armv7m/stm32f4/stm32f4xx_conf.h rename to mkrtos_knl/arch/cortex-m4/stm32f4/stm32f4xx_conf.h diff --git a/mkrtos_knl/arch/armv7m/stm32f4/stm32f4xx_it.h b/mkrtos_knl/arch/cortex-m4/stm32f4/stm32f4xx_it.h similarity index 100% rename from mkrtos_knl/arch/armv7m/stm32f4/stm32f4xx_it.h rename to mkrtos_knl/arch/cortex-m4/stm32f4/stm32f4xx_it.h diff --git a/mkrtos_knl/arch/armv7m/stm32f4/system_stm32f4xx.c b/mkrtos_knl/arch/cortex-m4/stm32f4/system_stm32f4xx.c similarity index 100% rename from mkrtos_knl/arch/armv7m/stm32f4/system_stm32f4xx.c rename to mkrtos_knl/arch/cortex-m4/stm32f4/system_stm32f4xx.c diff --git a/mkrtos_knl/arch/cortex-m4/syscall.S b/mkrtos_knl/arch/cortex-m4/syscall.S new file mode 100755 index 000000000..b9a8e3cc6 --- /dev/null +++ b/mkrtos_knl/arch/cortex-m4/syscall.S @@ -0,0 +1,109 @@ +.syntax unified +@ .cpu cortex-m3 +.thumb + +.global syscall_handler_get +/** +* @brief syscall结束时到这儿 +*/ +.type syscall_exit, %function +syscall_exit: + svc 1 + b . + +/** +* void syscall_ret_user(int ret_val); +* @brief 回到用户模式 +*/ +.type syscall_ret_user, %function +syscall_ret_user: + //存放返回值 + + //还原msp的值 + mrs r0, msp + add r0, #0x20 + ldmfd r0!,{r4-r11} + msr msp,r0 + pop {r0,r1,r2,lr} + + msr CONTROL, r1 + CPSIE I + bx lr + +/** +* void SVC_Handler(void); +* @brief +*/ +.global SVC_Handler +.type SVC_Handler, %function +SVC_Handler: +CPSID I + TST.W LR, #4 + ITE EQ + MRSEQ R1, MSP + MRSNE R1, PSP + //获得svc的调用号 + LDR R2, [R1, #24] + LDRB R2, [R2, #-2] + + cmp r2,#128 + beq SYS_CALL + cmp r2,#1 + beq TO_USER + cmp r2,#2 +// beq enter_fchannel +// cmp r2,#3 +// beq exit_fchannel + b TO_END +TO_USER: + B syscall_ret_user + +SYS_CALL: + //获取堆栈地址 + mov r0,r1 + //放入之前的栈地址 + mrs r1,CONTROL + + push {r0,r1,r2,lr} + //svc 128 + mov r1, r7 + //获得需要调用的syscall函数的地址 + push {r0-r2,lr} + blx syscall_handler_get + mov r3,r0 + pop {r0-r2,lr} + + //r4-r11 压入到内核栈中 + stmfd sp!,{r4-r11} + //压入到用户栈中 + stmfd r0,{r4-r11} + //取出PSR PC LR R12 R3 R2 R1 R0 + ldmfd r0,{r4-r11} + //压入到内核栈中 + stmfd sp!,{r4-r11} + + //取出lr与pc放到栈中 + mov r0,sp + ldr r2, =syscall_exit + //lr + str r2, [r0, #20] + //pc + str r3, [r0, #24] + ldr r3, =0x01000000 + str r3, [r0, #28] + + //重新设置control + mrs r0, CONTROL + bic r0, r0, #0x03 + msr CONTROL, r0 + + dsb + isb + orr lr, lr, #0x18 + bic lr, lr, #0x04 + CPSIE I + bx lr + +TO_END: +CPSIE I + bx lr diff --git a/mkrtos_knl/drivers/CMakeLists.txt b/mkrtos_knl/drivers/CMakeLists.txt index 26b7ab2d7..ef4ca9974 100755 --- a/mkrtos_knl/drivers/CMakeLists.txt +++ b/mkrtos_knl/drivers/CMakeLists.txt @@ -4,7 +4,7 @@ file(GLOB deps *.c *.S) add_library(drv STATIC ${deps}) include_directories( - ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/armv7m/${CONFIG_CPU_TYPE} + ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/${CONFIG_ARCH}/${CONFIG_CPU_TYPE} ) if (${CONFIG_CPU_TYPE} STREQUAL "stm32f1") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DSTM32F10X_XL ") @@ -35,6 +35,8 @@ elseif(${CONFIG_CPU_TYPE} STREQUAL "swm34s" ) ${CMAKE_SOURCE_DIR}/mkrtos_bsp/SWM34/SWM341_StdPeriph_Driver/CMSIS/CoreSupport ${CMAKE_SOURCE_DIR}/mkrtos_bsp/SWM34/SWM341_StdPeriph_Driver/SWM341_StdPeriph_Driver ) +elseif(${CONFIG_CPU_TYPE} STREQUAL "aarch64_qemu" ) + endif() add_subdirectory(${CONFIG_CPU_TYPE}) diff --git a/mkrtos_knl/drivers/aarch64_qemu/CMakeLists.txt b/mkrtos_knl/drivers/aarch64_qemu/CMakeLists.txt new file mode 100755 index 000000000..c6fdccbf8 --- /dev/null +++ b/mkrtos_knl/drivers/aarch64_qemu/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.13) + +file(GLOB_RECURSE deps *.c *.S) + +add_library(knl_drv STATIC ${deps}) + +target_include_directories( + knl_drv + PUBLIC + + ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/${CONFIG_ARCH}/${CONFIG_CPU_TYPE} + ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/${CONFIG_ARCH}/ + ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/lib + ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/knl + ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/drv + ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/inc + +) diff --git a/mkrtos_knl/drivers/aarch64_qemu/systick/systick.c b/mkrtos_knl/drivers/aarch64_qemu/systick/systick.c new file mode 100755 index 000000000..610afd12d --- /dev/null +++ b/mkrtos_knl/drivers/aarch64_qemu/systick/systick.c @@ -0,0 +1,19 @@ + +#include "arch.h" +#include "thread.h" +#include "futex.h" +static umword_t sys_tick_cnt; + +umword_t sys_tick_cnt_get(void) +{ + return 0; +} + +void SysTick_Handler(void) +{ + // 进行上下文切换 + thread_sched(); + sys_tick_cnt++; + thread_timeout_check(1); + futex_timeout_times_tick(); +} diff --git a/mkrtos_knl/drivers/aarch64_qemu/systick/timer.c b/mkrtos_knl/drivers/aarch64_qemu/systick/timer.c new file mode 100755 index 000000000..5eddc61fe --- /dev/null +++ b/mkrtos_knl/drivers/aarch64_qemu/systick/timer.c @@ -0,0 +1,85 @@ +#include +#include +#include +#include + +#define GENERIC_TIMER_IRQ 30 + +static unsigned int arch_timer_rate; + +static int generic_timer_init(void) +{ + asm volatile( + "mov x0, #1\n" + "msr cntp_ctl_el0, x0" + : + : + : "memory"); + + return 0; +} + +static int generic_timer_reset(unsigned int val) +{ + asm volatile( + "msr cntp_tval_el0, %x[timer_val]" + : + : [timer_val] "r"(val) + : "memory"); + + return 0; +} + +static unsigned int generic_timer_get_freq(void) +{ + unsigned int freq; + + asm volatile( + "mrs %0, cntfrq_el0" + : "=r"(freq) + : + : "memory"); + + return freq; +} + +static void enable_timer_interrupt(int inx) +{ + switch (inx) + { + case 0: + writel(CNT_PNS_IRQ, TIMER_CNTRL0); + break; + case 1: + writel(CNT_PNS_IRQ, TIMER_CNTRL1); + break; + case 2: + writel(CNT_PNS_IRQ, TIMER_CNTRL2); + break; + case 3: + writel(CNT_PNS_IRQ, TIMER_CNTRL3); + break; + } +} + +void timer_init(int cpu) +{ + arch_timer_rate = generic_timer_get_freq(); + arch_timer_rate /= CONFIG_SYS_SCHE_HZ; + + generic_timer_init(); + generic_timer_reset(arch_timer_rate); + + gic2_set_unmask(arm_gicv2_get_global(), GENERIC_TIMER_IRQ); + gic2_set_target_cpu(arm_gicv2_get_global(), GENERIC_TIMER_IRQ, 1 << cpu); + printk("cpu:%d timer dis:0x%x\n", arch_get_current_cpu_id(), + gic2_get_target_cpu(arm_gicv2_get_global(), GENERIC_TIMER_IRQ)); + + // enable_timer_interrupt(cpu); + // write_sysreg(0x3UL, cntkctl_el1); + // write_sysreg(0x1UL, cnthctl_el2); +} +void handle_timer_irq(void) +{ + generic_timer_reset(arch_timer_rate); +} diff --git a/mkrtos_knl/drivers/aarch64_qemu/uart/uart.c b/mkrtos_knl/drivers/aarch64_qemu/uart/uart.c new file mode 100755 index 000000000..feb0987be --- /dev/null +++ b/mkrtos_knl/drivers/aarch64_qemu/uart/uart.c @@ -0,0 +1,194 @@ + +#include "mk_sys.h" +#include "types.h" +#include "uart/uart.h" +#include "init.h" +#include "queue.h" +#include + +#define UART01x_DR 0x00 /* Data read or written from the interface. */ +#define UART01x_RSR 0x04 /* Receive status register (Read). */ +#define UART01x_ECR 0x04 /* Error clear register (Write). */ +#define UART010_LCRH 0x08 /* Line control register, high byte. */ +#define ST_UART011_DMAWM 0x08 /* DMA watermark configure register. */ +#define UART010_LCRM 0x0C /* Line control register, middle byte. */ +#define ST_UART011_TIMEOUT 0x0C /* Timeout period register. */ +#define UART010_LCRL 0x10 /* Line control register, low byte. */ +#define UART010_CR 0x14 /* Control register. */ +#define UART01x_FR 0x18 /* Flag register (Read only). */ +#define UART010_IIR 0x1C /* Interrupt identification register (Read). */ +#define UART010_ICR 0x1C /* Interrupt clear register (Write). */ +#define ST_UART011_LCRH_RX 0x1C /* Rx line control register. */ +#define UART01x_ILPR 0x20 /* IrDA low power counter register. */ +#define UART011_IBRD 0x24 /* Integer baud rate divisor register. */ +#define UART011_FBRD 0x28 /* Fractional baud rate divisor register. */ +#define UART011_LCRH 0x2c /* Line control register. */ +#define UART011_LCRH_WLEN_8 0x60 +#define ST_UART011_LCRH_TX 0x2c /* Tx Line control register. */ +#define UART011_CR 0x30 /* Control register. */ +#define UART011_IFLS 0x34 /* Interrupt fifo level select. */ +#define UART011_IMSC 0x38 /* Interrupt mask. */ +#define UART011_RIS 0x3c /* Raw interrupt status. */ +#define UART011_MIS 0x40 /* Masked interrupt status. */ +#define UART011_ICR 0x44 /* Interrupt clear register. */ +#define UART011_DMACR 0x48 /* DMA control register. */ +#define ST_UART011_XFCR 0x50 /* XON/XOFF control register. */ +#define ST_UART011_XON1 0x54 /* XON1 register. */ +#define ST_UART011_XON2 0x58 /* XON2 register. */ +#define ST_UART011_XOFF1 0x5C /* XON1 register. */ +#define ST_UART011_XOFF2 0x60 /* XON2 register. */ +#define ST_UART011_ITCR 0x80 /* Integration test control register. */ +#define ST_UART011_ITIP 0x84 /* Integration test input register. */ +#define ST_UART011_ABCR 0x100 /* Autobaud control register. */ +#define ST_UART011_ABIMSC 0x15C /* Autobaud interrupt mask/clear register. */ + +#define UART011_FR_RI 0x100 +#define UART011_FR_TXFE 0x080 +#define UART011_FR_RXFF 0x040 +#define UART01x_FR_TXFF 0x020 +#define UART01x_FR_RXFE 0x010 +#define UART01x_FR_BUSY 0x008 +#define UART01x_FR_DCD 0x004 +#define UART01x_FR_DSR 0x002 +#define UART01x_FR_CTS 0x001 +#define UART01x_FR_TMSK (UART01x_FR_TXFF + UART01x_FR_BUSY) + +#define UART011_CR_CTSEN 0x8000 /* CTS hardware flow control */ +#define UART011_CR_RTSEN 0x4000 /* RTS hardware flow control */ +#define UART011_CR_OUT2 0x2000 /* OUT2 */ +#define UART011_CR_OUT1 0x1000 /* OUT1 */ +#define UART011_CR_RTS 0x0800 /* RTS */ +#define UART011_CR_DTR 0x0400 /* DTR */ +#define UART011_CR_RXE 0x0200 /* receive enable */ +#define UART011_CR_TXE 0x0100 /* transmit enable */ +#define UART011_CR_LBE 0x0080 /* loopback enable */ +#define UART010_CR_RTIE 0x0040 +#define UART010_CR_TIE 0x0020 +#define UART010_CR_RIE 0x0010 +#define UART010_CR_MSIE 0x0008 +#define ST_UART011_CR_OVSFACT 0x0008 /* Oversampling factor */ +#define UART01x_CR_IIRLP 0x0004 /* SIR low power mode */ +#define UART01x_CR_SIREN 0x0002 /* SIR enable */ +#define UART01x_CR_UARTEN 0x0001 /* UART enable */ + +#define UART011_OEIM (1 << 10) /* overrun error interrupt mask */ +#define UART011_BEIM (1 << 9) /* break error interrupt mask */ +#define UART011_PEIM (1 << 8) /* parity error interrupt mask */ +#define UART011_FEIM (1 << 7) /* framing error interrupt mask */ +#define UART011_RTIM (1 << 6) /* receive timeout interrupt mask */ +#define UART011_TXIM (1 << 5) /* transmit interrupt mask */ +#define UART011_RXIM (1 << 4) /* receive interrupt mask */ +#define UART011_DSRMIM (1 << 3) /* DSR interrupt mask */ +#define UART011_DCDMIM (1 << 2) /* DCD interrupt mask */ +#define UART011_CTSMIM (1 << 1) /* CTS interrupt mask */ +#define UART011_RIMIM (1 << 0) /* RI interrupt mask */ + +#define UART011_OEIS (1 << 10) /* overrun error interrupt status */ +#define UART011_BEIS (1 << 9) /* break error interrupt status */ +#define UART011_PEIS (1 << 8) /* parity error interrupt status */ +#define UART011_FEIS (1 << 7) /* framing error interrupt status */ +#define UART011_RTIS (1 << 6) /* receive timeout interrupt status */ +#define UART011_TXIS (1 << 5) /* transmit interrupt status */ +#define UART011_RXIS (1 << 4) /* receive interrupt status */ +#define UART011_DSRMIS (1 << 3) /* DSR interrupt status */ +#define UART011_DCDMIS (1 << 2) /* DCD interrupt status */ +#define UART011_CTSMIS (1 << 1) /* CTS interrupt status */ +#define UART011_RIMIS (1 << 0) /* RI interrupt status */ + +#define UART011_OEIC (1 << 10) /* overrun error interrupt clear */ +#define UART011_BEIC (1 << 9) /* break error interrupt clear */ +#define UART011_PEIC (1 << 8) /* parity error interrupt clear */ +#define UART011_FEIC (1 << 7) /* framing error interrupt clear */ +#define UART011_RTIC (1 << 6) /* receive timeout interrupt clear */ +#define UART011_TXIC (1 << 5) /* transmit interrupt clear */ +#define UART011_RXIC (1 << 4) /* receive interrupt clear */ +#define UART011_DSRMIC (1 << 3) /* DSR interrupt clear */ +#define UART011_DCDMIC (1 << 2) /* DCD interrupt clear */ +#define UART011_CTSMIC (1 << 1) /* CTS interrupt clear */ +#define UART011_RIMIC (1 << 0) /* RI interrupt clear */ + +#define UART011_BASE_ADDR 0x9000000 //!< 寄存器基地址 +#define UART011_FREQ 0x0 //!< 频率 +#define UART011_DEFAULT_BAUD 115200 +static uart_t uart = { + .baud = 115200}; + +uart_t *uart_get_global(void) +{ + return &uart; +} +static void uart_set_baud(int baud) +{ + uint32_t fi_val = UART011_FREQ * 4 / baud; + + write_reg32(UART011_BASE_ADDR + UART011_FBRD, fi_val & 0x3f); + write_reg32(UART011_BASE_ADDR + UART011_IBRD, fi_val >> 6); +} +#define QUEUE_LEN 129 +static queue_t queue; +static uint8_t queue_data[QUEUE_LEN]; +void uart_tigger(irq_entry_t *irq) +{ + // q_enqueue(&queue, USART_ReceiveData(USART1)); + /*TODO:*/ +} + +void uart_init(void) +{ + q_init(&queue, queue_data, QUEUE_LEN); + write_reg32(UART011_BASE_ADDR + UART011_CR, UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_RXE); + if (UART011_FREQ) + { + uart_set_baud(UART011_DEFAULT_BAUD); + } + write_reg32(UART011_BASE_ADDR + UART011_LCRH, UART011_LCRH_WLEN_8); + write_reg32(UART011_BASE_ADDR + UART011_IMSC, 0); + + int i = 3000000; + + while (i--) + { + if (!(read_reg32(UART011_BASE_ADDR + UART01x_FR) & UART01x_FR_BUSY)) + { + break; + } + } +} +INIT_HIGH_HAD(uart_init); + + +void uart_set(uart_t *uart) +{ + uart_set_baud(uart->baud); +} +void uart_putc(uart_t *uart, int data) +{ + int i = 3000000; + + while (i--) + { + if (!(read_reg32(UART011_BASE_ADDR + UART01x_FR) & UART01x_FR_TXFF)) + { + break; + } + } + write_reg32(UART011_BASE_ADDR + UART01x_DR, data & 0xff); +} +int uart_getc(uart_t *uart) +{ + uint8_t e; + umword_t status; + + status = cpulock_lock(); + if (q_dequeue(&queue, &e) >= 0) + { + cpulock_set(status); + return e; + } + cpulock_set(status); + return -1; +} +int uart_get_len(uart_t *uart) +{ + return q_queue_len(&queue); +} diff --git a/mkrtos_knl/drivers/stm32f2/CMakeLists.txt b/mkrtos_knl/drivers/stm32f2/CMakeLists.txt index 717085f29..955ed52c0 100755 --- a/mkrtos_knl/drivers/stm32f2/CMakeLists.txt +++ b/mkrtos_knl/drivers/stm32f2/CMakeLists.txt @@ -12,5 +12,5 @@ target_include_directories( ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/drv ${CMAKE_SOURCE_DIR}/mkrtos_bsp/STM32/STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/CMSIS/Include ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/inc - + ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/${CONFIG_ARCH}/ ) diff --git a/mkrtos_knl/inc/drv/timer/timer.h b/mkrtos_knl/inc/drv/timer/timer.h new file mode 100644 index 000000000..6a100c5d5 --- /dev/null +++ b/mkrtos_knl/inc/drv/timer/timer.h @@ -0,0 +1,4 @@ +#pragma once + +void timer_init(int cpu); +void handle_timer_irq(void); diff --git a/mkrtos_knl/inc/knl/buddy.h b/mkrtos_knl/inc/knl/buddy.h new file mode 100755 index 000000000..e37d7aff8 --- /dev/null +++ b/mkrtos_knl/inc/knl/buddy.h @@ -0,0 +1,50 @@ +#pragma once + +#include +#include +#include +#include + +typedef struct buddy_entry +{ + slist_head_t next; //!< next + addr_t addr; //!< start addr + struct buddy_entry *parent; //!< 从哪一个分出来 +} buddy_entry_t; + +#define BUDDY_ENTRY_ATTR_MASK 0xfULL +#define BUDDY_ENTRY_VALID(this) (!!((this)->addr & 0x1ULL)) //!< 1代表有效 +#define BUDDY_ENTRY_USED(this) (!!((this)->addr & 0x2ULL)) //!< 1代表被分配了 +#define BUDDY_ENTRY_IS_L(this) (!!(((this)->addr & 0xCULL) == 0xC)) //!< 伙伴地左边 +#define BUDDY_ENTRY_IS_R(this) (!!(((this)->addr & 0xCULL) == 0x4)) +#define BUDDY_ENTRY_ADDR(this) ((this)->addr & ~(BUDDY_ENTRY_ATTR_MASK)) //!< 获取使用的地址 + +typedef struct buddy_head +{ + slist_head_t b_order; //!< 链表的入口 + mword_t nr_free; //!< 多少个可用的块 +} buddy_head_t; + +#define BUDDY_MAX_ORDER 12 + +typedef struct buddy_order +{ + buddy_head_t order_tab[BUDDY_MAX_ORDER]; // max 16MB + addr_t heap_addr; + spinlock_t lock; + size_t heap_size; +} buddy_order_t; + +buddy_order_t *buddy_get_alloter(void); +int buddy_init(buddy_order_t *buddy, addr_t start_addr, size_t size); +void *buddy_alloc(buddy_order_t *buddy, size_t size); +void buddy_free(buddy_order_t *buddy, void *mem); +static inline size_t buddy_get_heap_size(buddy_order_t *buddy) +{ + return buddy->heap_size; +} +static inline addr_t buddy_get_heap_addr(buddy_order_t *buddy) +{ + return buddy->heap_addr; +} +void buddy_print(buddy_order_t *buddy); diff --git a/mkrtos_knl/inc/knl/mm_page.h b/mkrtos_knl/inc/knl/mm_page.h index 73e36eae6..5814bf79e 100644 --- a/mkrtos_knl/inc/knl/mm_page.h +++ b/mkrtos_knl/inc/knl/mm_page.h @@ -36,7 +36,7 @@ static inline void mm_entry_set_addr(mm_addr_t *addr, addr_t new_addr) } #define PAGE_NR 64 -#define PAGE_SIZE 512 +#define PAGE_SIZE (1 << CONFIG_PAGE_SHIFT) typedef struct mm_pages { diff --git a/mkrtos_knl/inc/knl/mpu.h b/mkrtos_knl/inc/knl/mpu.h index c68832957..5402a38c8 100644 --- a/mkrtos_knl/inc/knl/mpu.h +++ b/mkrtos_knl/inc/knl/mpu.h @@ -37,6 +37,10 @@ static inline void mpu_region_set(int inx, umword_t rbar, umword_t rasr) static inline void mpu_region_clr(int inx) { } -void mpu_switch_to(void); -void mpu_switch_to_task(struct task *tk); +static inline void mpu_switch_to(void) +{ +} +static inline void mpu_switch_to_task(struct task *tk) +{ +} #endif diff --git a/mkrtos_knl/inc/knl/slab.h b/mkrtos_knl/inc/knl/slab.h new file mode 100755 index 000000000..154210b16 --- /dev/null +++ b/mkrtos_knl/inc/knl/slab.h @@ -0,0 +1,45 @@ +#pragma once + +#include +#include +#include + +#define SLAB_NAME_LEN 8 + +#define SLAB_BLOCK_MAGIC 0x1212343456567878 + +typedef struct slab_block_head +{ + slist_head_t next; + mword_t used; + mword_t magic; + char user_data[0]; +} slab_block_head_t; + +typedef struct slab_head +{ + slist_head_t next; + void *buddy_addr; + // size_t size; +} slab_head_t; + +#define SLAB_MIN_NUM 2 //!< 单次申请buddy内存时,保证里面至少有两块 + +// slab内存从buddy中分配 +typedef struct slab +{ + slist_head_t head; + // TODO: char name[SLAB_NAME_LEN]; + size_t align_size; //!< 每个slab项大小 + slist_head_t free_block; + size_t free_nr; + slist_head_t used_block; + size_t total_nr; + spinlock_t lock; +} slab_t; + +slab_t *slab_create(size_t align_size, const char *name); +void slab_release(slab_t *slab); +void *slab_alloc(slab_t *slab); +void slab_free(slab_t *slab, void *mem); +void slab_print(slab_t *slab); diff --git a/mkrtos_knl/inc/knl/thread.h b/mkrtos_knl/inc/knl/thread.h index 66c038b7c..529ab72df 100755 --- a/mkrtos_knl/inc/knl/thread.h +++ b/mkrtos_knl/inc/knl/thread.h @@ -15,7 +15,7 @@ #include "util.h" #include "arch.h" #include "ref.h" -#define THREAD_BLOCK_SIZE 0x400 //!< 线程块大小,栈在块的顶部 +#include struct task; typedef struct task task_t; struct thread; diff --git a/mkrtos_knl/inc/knl/util.h b/mkrtos_knl/inc/knl/util.h index a681eae1b..57e724a50 100755 --- a/mkrtos_knl/inc/knl/util.h +++ b/mkrtos_knl/inc/knl/util.h @@ -14,12 +14,16 @@ #define ROUND_UP(a, b) ROUND(a, b) //!< a除b向上取整数 #define ROUND_DOWN(a, b) ((a) / (b)) //!< a/b向下取整 +#define GET_LSB(a, b) (a & (~((~0ULL) << (b)))) +#define MASK_LSB(a, b) (a & ((~0ULL) << (b))) //!< 屏蔽低位 + #define ARRARY_LEN(a) (sizeof(a) / sizeof((a)[0])) //!< 数组长度 -#define ALIGN(mem, align) (((mem) + ((align)-1)) & (~((align)-1))) //!< 向上对齐 -#define ALIGN_DOWN(mem, align) ((mem) & (~((align)-1))) //!< 向下对齐 -#define MASK_LSB(data, inx) (((data) >> (inx)) << (inx)) //!< 屏蔽低位 +#define ALIGN(mem, align) (((mem) + ((align) - 1)) & (~((align) - 1))) //!< 向上对齐 +#define ALIGN_DOWN(mem, align) ((mem) & (~((align) - 1))) //!< 向下对齐 +#define PACKED __attribute__((packed)) +#define SECTION(section) __attribute__((__section__(section))) #define __ALIGN__(size) __attribute__((aligned(size))) #define container_of(ptr, type, member) \ @@ -27,6 +31,19 @@ #define USED __attribute__((used)) +#define __ARG_PLACEHOLDER_1 0, +#define __take_second_arg(__ignored, val, ...) val +#define __is_defined(x) ___is_defined(x) +#define ___is_defined(val) ____is_defined(__ARG_PLACEHOLDER_##val) +#define ____is_defined(arg1_or_junk) __take_second_arg(arg1_or_junk 1, 0) +#define __or(x, y) ___or(x, y) +#define ___or(x, y) ____or(__ARG_PLACEHOLDER_##x, y) +#define ____or(arg1_or_junk, y) __take_second_arg(arg1_or_junk 1, y) +#define IS_BUILTIN(option) __is_defined(option) +#define IS_MODULE(option) __is_defined(option##_MODULE) + +#define IS_ENABLED(option) __or(IS_BUILTIN(option), IS_MODULE(option)) + int ffs(int x); int clz(umword_t x); diff --git a/mkrtos_knl/knl/CMakeLists.txt b/mkrtos_knl/knl/CMakeLists.txt index 719e5290a..cf32430a3 100755 --- a/mkrtos_knl/knl/CMakeLists.txt +++ b/mkrtos_knl/knl/CMakeLists.txt @@ -2,11 +2,19 @@ cmake_minimum_required(VERSION 3.13) file(GLOB_RECURSE deps *.c *.S) + +if (NOT ${CONFIG_SMP} STREQUAL "y" ) + list(REMOVE_ITEM deps ${CMAKE_SOURCE_DIR}/mkrtos_knl/knl/buddy.c) + list(REMOVE_ITEM deps ${CMAKE_SOURCE_DIR}/mkrtos_knl/knl/slab.c) +endif() + add_library(knl STATIC ${deps}) + target_include_directories( knl PUBLIC - ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/armv7m/${CONFIG_CPU_TYPE} + ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/${CONFIG_ARCH}/${CONFIG_CPU_TYPE} + ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/${CONFIG_ARCH}/ ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/lib ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/knl diff --git a/mkrtos_knl/knl/buddy.c b/mkrtos_knl/knl/buddy.c new file mode 100755 index 000000000..e7dbfb774 --- /dev/null +++ b/mkrtos_knl/knl/buddy.c @@ -0,0 +1,382 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define BUDDY_ENTRY_MAX_CN 1024 + +static buddy_entry_t buddy_entry_simp_slab[BUDDY_ENTRY_MAX_CN]; +static buddy_order_t buddy_kmem; + +static inline size_t to_size(size_t order); + +static inline void buddy_entry_set_use_state(buddy_entry_t *be, bool_t state) +{ + be->addr &= ~0x2ULL; + be->addr |= (!!state) << 1; +} +static inline void buddy_entry_set_valid_state(buddy_entry_t *be, bool_t state) +{ + be->addr &= ~0x1ULL; + be->addr |= (!!state) << 0; +} +static inline void buddy_entry_set_addr(buddy_entry_t *be, addr_t addr) +{ + be->addr = GET_LSB(be->addr, 2) | MASK_LSB(addr, 2); +} +static inline void buddy_entry_init(buddy_entry_t *be, addr_t addr) +{ + be->addr &= ~(BUDDY_ENTRY_ATTR_MASK); + be->addr |= 1 | addr; +} +static inline void buddy_entry_set_lr(buddy_entry_t *be, bool_t l) +{ + be->addr &= ~0xCULL; + be->addr |= ((l ? 0x3 : 0x1) << 2ULL); +} +static inline void buddy_entry_clr_lr(buddy_entry_t *be) +{ + be->addr &= ~0xCULL; +} + +static buddy_entry_t *buddy_entry_alloc(void) +{ + for (int i = 0; i < BUDDY_ENTRY_MAX_CN; i++) + { + if (!BUDDY_ENTRY_VALID(&buddy_entry_simp_slab[i])) + { + buddy_entry_simp_slab[i].addr = 0; + buddy_entry_simp_slab[i].parent = NULL; + buddy_entry_set_valid_state(&buddy_entry_simp_slab[i], TRUE); + // printk("allod buddy entry %d.\n", i); + return &buddy_entry_simp_slab[i]; + } + } + return NULL; +} +static void buddy_entry_free(buddy_entry_t *be) +{ + be->addr &= ~(BUDDY_ENTRY_ATTR_MASK); +} + +buddy_order_t *buddy_get_alloter(void) +{ + return &buddy_kmem; +} + +int buddy_init(buddy_order_t *buddy, addr_t start_addr, size_t size) +{ + assert(buddy); + + if ((start_addr & (PAGE_SIZE - 1)) != 0) + { + return -1; + } + buddy->heap_addr = start_addr; + spinlock_init(&buddy->lock); + for (int i = 0; i < BUDDY_MAX_ORDER; i++) + { + slist_init(&buddy->order_tab[i].b_order); + } + + size_t remain_size = size; + addr_t add_addr = buddy->heap_addr; + + // 内存分布到不同地order中= + while (remain_size) + { + int i_ffs = ffs(remain_size); + i_ffs -= PAGE_SHIFT; + buddy_entry_t *new_be = buddy_entry_alloc(); + if (!new_be) + { + return -1; + } + buddy_entry_init(new_be, add_addr); + slist_add(&buddy->order_tab[i_ffs - 1].b_order, &new_be->next); + buddy->order_tab[i_ffs - 1].nr_free++; + + remain_size = size - to_size(i_ffs); + add_addr += to_size(i_ffs); + } + buddy->heap_size = size; + return 0; +} + +static buddy_entry_t *buddy_order_find_free(buddy_head_t *buddy_head) +{ + buddy_entry_t *be_tmp = NULL; + + slist_foreach(be_tmp, &buddy_head->b_order, next) + { + if (!BUDDY_ENTRY_USED(be_tmp)) + { + // 没有被使用 + return be_tmp; + } + } + return NULL; +} +static inline size_t to_size(size_t order) +{ + return (1 << order) << PAGE_SHIFT; +} +/** + * 从buddy指定位置向下分裂到指定位置,并返回分裂后的块中的一块 + */ +static buddy_entry_t *buddy_order_div(buddy_order_t *buddy, mword_t st_order) +{ + assert(st_order < BUDDY_MAX_ORDER); + assert(st_order > 0); + + buddy_entry_t *free_b = buddy_order_find_free(&buddy->order_tab[st_order]); + + if (!free_b) + { + return NULL; + } + buddy_entry_set_use_state(free_b, TRUE); + buddy->order_tab[st_order].nr_free--; + + buddy_entry_t *new_l = buddy_entry_alloc(); + buddy_entry_t *new_r = buddy_entry_alloc(); + + if (!new_l || !new_r) + { + if (new_l) + { + buddy_entry_free(new_l); + } + return NULL; + } + + addr_t div_addr = BUDDY_ENTRY_ADDR(free_b); + + new_l->parent = free_b; + new_r->parent = free_b; + buddy_entry_init(new_l, div_addr); + buddy_entry_init(new_r, div_addr + to_size(st_order - 1)); + buddy_entry_set_lr(new_l, TRUE); + buddy_entry_set_lr(new_r, FALSE); + slist_add(&buddy->order_tab[st_order - 1].b_order, &new_l->next); + slist_add(&buddy->order_tab[st_order - 1].b_order, &new_r->next); + + // printk("div: l %d, r %d,valid %d, used %d, addr 0x%x, block size 0x%x\n", + // BUDDY_ENTRY_IS_L(new_l), + // BUDDY_ENTRY_IS_R(new_l), + // BUDDY_ENTRY_VALID(new_l), + // BUDDY_ENTRY_USED(new_l), + // BUDDY_ENTRY_ADDR(new_l), to_size(st_order - 1)); + // printk("div: l %d, r %d,valid %d, used %d, addr 0x%x, block size 0x%x\n", + // BUDDY_ENTRY_IS_L(new_r), + // BUDDY_ENTRY_IS_R(new_r), + // BUDDY_ENTRY_VALID(new_r), + // BUDDY_ENTRY_USED(new_r), + // BUDDY_ENTRY_ADDR(new_r), to_size(st_order - 1)); + + buddy->order_tab[st_order - 1].nr_free += 2; + return new_l; +} +void *buddy_alloc(buddy_order_t *buddy, size_t size) +{ + size_t need_ffs; + void *ret_mem = NULL; + + need_ffs = ffs(size); + need_ffs += is_power_of_2(size) ? 0 : 1; + + if (need_ffs < PAGE_SHIFT) + { // 至少4K + need_ffs = PAGE_SHIFT; + } + need_ffs -= PAGE_SHIFT; + + if (need_ffs >= BUDDY_MAX_ORDER) + { + return NULL; + } + + mword_t l_state = spinlock_lock(&buddy->lock); + + if (buddy->order_tab[need_ffs].nr_free > 0) + { + // 有空闲的直接分配 + buddy_entry_t *free_b = buddy_order_find_free(&buddy->order_tab[need_ffs]); + + buddy->order_tab[need_ffs].nr_free--; + buddy_entry_set_use_state(free_b, TRUE); + ret_mem = (void *)BUDDY_ENTRY_ADDR(free_b); + goto end; + } + for (size_t st_inx = need_ffs + 1; st_inx < BUDDY_MAX_ORDER; st_inx++) + { + if (st_inx >= BUDDY_MAX_ORDER) + { + // 超过了可分配的大小直接退出 + spinlock_set(&buddy->lock, l_state); + return NULL; + } + if (buddy->order_tab[st_inx].nr_free > 0) + { + buddy_entry_t *div; + + do + { + div = buddy_order_div(buddy, st_inx); //!< 不断地划分大小,直到大小合适 + st_inx--; + if (st_inx == need_ffs) + { + break; + } + // buddy_print(buddy); + } while (div); + if (!div) + { + ret_mem = NULL; + goto end; + } + buddy->order_tab[st_inx].nr_free--; + buddy_entry_set_use_state(div, TRUE); + ret_mem = (void *)BUDDY_ENTRY_ADDR(div); + goto end; + } + } +end: + spinlock_set(&buddy->lock, l_state); + return ret_mem; +} +static inline addr_t get_buddy_addr(buddy_entry_t *merge_be, size_t size) +{ + assert(is_power_of_2(size)); + + if (BUDDY_ENTRY_IS_L(merge_be)) + { + return BUDDY_ENTRY_ADDR(merge_be) + size; + } + else if (BUDDY_ENTRY_IS_R(merge_be)) + { + return BUDDY_ENTRY_ADDR(merge_be) - size; + } + else + { + assert(0); + } +} +static inline addr_t get_buddy_start(buddy_entry_t *merge_be, size_t size) +{ + assert(is_power_of_2(size)); + + if (BUDDY_ENTRY_IS_L(merge_be)) + { + return BUDDY_ENTRY_ADDR(merge_be); + } + else if (BUDDY_ENTRY_IS_R(merge_be)) + { + return BUDDY_ENTRY_ADDR(merge_be) - size; + } + else + { + assert(0); + } +} +static buddy_entry_t *buddy_merge(buddy_order_t *buddy, buddy_entry_t *merge_be, int st_ffs) +{ + if (st_ffs >= BUDDY_MAX_ORDER || merge_be->parent == NULL) + { + return NULL; + } + addr_t buddy_addr = get_buddy_addr(merge_be, to_size(st_ffs)); + buddy_entry_t *tmp = NULL; + + slist_foreach(tmp, &buddy->order_tab[st_ffs].b_order, next) + { + if (BUDDY_ENTRY_ADDR(tmp) == (addr_t)buddy_addr) + { + if (BUDDY_ENTRY_USED(tmp)) + { + return NULL; + } + // assert(!BUDDY_ENTRY_USED(tmp)); + assert(BUDDY_ENTRY_VALID(tmp)); + addr_t buddy_st_addr = get_buddy_start(tmp, to_size(st_ffs)); + + slist_del(&merge_be->next); + slist_del(&tmp->next); + buddy->order_tab[st_ffs].nr_free -= 2; + + assert(tmp->parent); + buddy_entry_set_use_state(tmp, FALSE); + + buddy_entry_free(merge_be); + buddy_entry_free(tmp); + buddy->order_tab[st_ffs + 1].nr_free++; + return tmp->parent; + } + } + return NULL; +} +void buddy_free(buddy_order_t *buddy, void *mem) +{ + addr_t free_addr = (addr_t)mem; + mword_t l_state = spinlock_lock(&buddy->lock); + + for (int i = 0; i < BUDDY_MAX_ORDER; i++) + { + buddy_entry_t *tmp = NULL; + + slist_foreach(tmp, &buddy->order_tab[i].b_order, next) + { + if (BUDDY_ENTRY_ADDR(tmp) == (addr_t)mem) + { + // assert(BUDDY_ENTRY_USED(tmp)); + assert(BUDDY_ENTRY_VALID(tmp)); + + if (BUDDY_ENTRY_USED(tmp)) + { + buddy_entry_set_use_state(tmp, FALSE); + buddy->order_tab[i].nr_free++; + } + buddy_entry_t *next = tmp; + + do + { + next = buddy_merge(buddy, next, i); + if (!next) + { + spinlock_set(&buddy->lock, l_state); + return; + } + i++; + // buddy_print(buddy); + } while (1); + } + } + } + spinlock_set(&buddy->lock, l_state); +} + +void buddy_print(buddy_order_t *buddy) +{ + // mword_t l_state = spinlock_test_and_lock(&buddy->lock); + printk("\n"); + for (int i = 0; i < BUDDY_MAX_ORDER; i++) + { + buddy_entry_t *tmp = NULL; + + slist_foreach(tmp, &buddy->order_tab[i].b_order, next) + { + printk("div: l %d, r %d,valid %d, used %d, addr 0x%x, block size 0x%x\n", + BUDDY_ENTRY_IS_L(tmp), + BUDDY_ENTRY_IS_R(tmp), + BUDDY_ENTRY_VALID(tmp), + BUDDY_ENTRY_USED(tmp), + BUDDY_ENTRY_ADDR(tmp), to_size(i)); + } + } + // spinlock_set(&buddy->lock, l_state); +} diff --git a/mkrtos_knl/knl/factory.c b/mkrtos_knl/knl/factory.c index 67e74fc9f..c762619be 100755 --- a/mkrtos_knl/knl/factory.c +++ b/mkrtos_knl/knl/factory.c @@ -37,14 +37,20 @@ static factory_t root_factory; * */ static factory_func factory_func_list[FACTORY_FUNC_MAX]; - +#if IS_ENABLED(CONFIG_BUDDY_SLAB) +#include +static slab_t *factory_slab; +#endif /** * @brief 在系统初始化时调用,初始化factoyr的内存 * */ static void factory_mem_init(void) { - // Nothing. +#if IS_ENABLED(CONFIG_BUDDY_SLAB) + factory_slab = slab_create(sizeof(factory_t), "factory"); + assert(factory_slab); +#endif } INIT_KOBJ_MEM(factory_mem_init); /** @@ -176,8 +182,13 @@ static void factory_init(factory_t *fac, umword_t max) */ static factory_t *fatory_create(ram_limit_t *lim, umword_t max) { - factory_t *kobj = mm_limit_alloc(lim, sizeof(factory_t)); + factory_t *kobj = NULL; +#if IS_ENABLED(CONFIG_BUDDY_SLAB) + kobj = slab_alloc(factory_slab); +#else + kobj = mm_limit_alloc(lim, sizeof(factory_t)); +#endif if (!kobj) { return NULL; diff --git a/mkrtos_knl/knl/futex.c b/mkrtos_knl/knl/futex.c index 6a8fc925f..48e6b82dd 100644 --- a/mkrtos_knl/knl/futex.c +++ b/mkrtos_knl/knl/futex.c @@ -271,7 +271,7 @@ static futex_lock_t *futex_find(futex_t *fst, void *uaddr) * @return int */ static int futex_dispose(futex_t *fst, uint32_t *uaddr, int futex_op, uint32_t val, - umword_t timeout /*val2*/, uint32_t uaddr2, uint32_t val3, int tid) + umword_t timeout /*val2*/, umword_t uaddr2, uint32_t val3, int tid) { thread_t *cur_th = thread_get_current(); diff --git a/mkrtos_knl/knl/globals.c b/mkrtos_knl/knl/globals.c index 714c14251..c8198dcc0 100755 --- a/mkrtos_knl/knl/globals.c +++ b/mkrtos_knl/knl/globals.c @@ -52,6 +52,9 @@ mem_t *mm_get_global(void) { return &global_mem; } +#if CONFIG_BUDDY_SLAB +#include +#endif /** * @brief 系统内存初始化 * @@ -60,10 +63,19 @@ static void mem_sys_init(void) { void *mem_block_data; mem_init(&global_mem); +#if CONFIG_BUDDY_SLAB + extern char _buddy_data_start[]; + extern char _buddy_data_end[]; + int ret; + ret = buddy_init(buddy_get_alloter(), (addr_t)_buddy_data_start, + (size_t)_buddy_data_end - (mword_t)_buddy_data_start); + assert(ret >= 0); +#else #if CONFIG_KNL_EXRAM mem_heap_add(mm_get_global(), (void *)CONFIG_EX_RAM_ADDR, CONFIG_EX_RAM_SIZE); #endif mem_heap_add(mm_get_global(), (void *)_ebss, CONFIG_KNL_DATA_SIZE - ((umword_t)_ebss - (umword_t)_sdata)); +#endif } INIT_MEM(mem_sys_init); diff --git a/mkrtos_knl/knl/mm.c b/mkrtos_knl/knl/mm.c index ee7a90190..2f4817764 100755 --- a/mkrtos_knl/knl/mm.c +++ b/mkrtos_knl/knl/mm.c @@ -168,7 +168,7 @@ again_alloc: void *split_addr = mem_split(_this, mem, (ptr_t)align_ptr - (ptr_t)mem); if (split_addr == NULL) { - *(((uint32_t *)(align_ptr)) - 1) = (uint32_t)mem; + *(((size_t *)(align_ptr)) - 1) = (size_t)mem; return align_ptr; } mem_free(_this, mem); @@ -189,7 +189,7 @@ again_alloc: void mem_free_align(mem_t *_this, void *f_mem) { struct mem_heap *mem; - void *real_mem; + umword_t *real_mem; int find = 0; umword_t status = spinlock_lock(&_this->lock); @@ -206,7 +206,7 @@ void mem_free_align(mem_t *_this, void *f_mem) if (mem == _this->heap_end) { - real_mem = (void *)(*(((uint32_t *)(f_mem)) - 1)); + real_mem = (umword_t *)(*(((umword_t *)(f_mem)) - 1)); mem_free(_this, real_mem); // #if MEM_TRACE // mem_trace(_this); diff --git a/mkrtos_knl/knl/scheduler.c b/mkrtos_knl/knl/scheduler.c index be733b166..138a3da83 100755 --- a/mkrtos_knl/knl/scheduler.c +++ b/mkrtos_knl/knl/scheduler.c @@ -129,4 +129,8 @@ sp_info_t *schde_to(void *usp, void *ksp, umword_t sp_type) } sched_reset = 1; return &next_th->sp; -} \ No newline at end of file +} +void sched_tail(void) +{ + /*TODO:*/ +} diff --git a/mkrtos_knl/knl/slab.c b/mkrtos_knl/knl/slab.c new file mode 100755 index 000000000..cd4991877 --- /dev/null +++ b/mkrtos_knl/knl/slab.c @@ -0,0 +1,146 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +slab_t *slab_create(size_t align_size, const char *name) +{ + // assert(is_order(align_size)); + align_size = ALIGN(align_size, MWORD_BYTES); + + size_t need_size = SLAB_MIN_NUM * (align_size + sizeof(slab_block_head_t)) + sizeof(slab_t); + size_t alloc_size = 1 << (is_power_of_2(need_size) ? ffs(need_size) : ffs(need_size) + 1); + + if (alloc_size < PAGE_SIZE) + { + alloc_size = PAGE_SIZE; + } + + void *mem = buddy_alloc(buddy_get_alloter(), alloc_size); + + if (!mem) + { + return NULL; + } + slab_t *tmp_slab = (slab_t *)mem; + + spinlock_init(&tmp_slab->lock); + slist_init(&tmp_slab->free_block); + slist_init(&tmp_slab->used_block); + slist_init(&tmp_slab->head); + tmp_slab->free_nr = 0; + tmp_slab->align_size = align_size; + tmp_slab->total_nr = 0; + + for (size_t i = 0; i < alloc_size / (align_size + sizeof(slab_block_head_t)); i++) + { + slab_block_head_t *slab_block = (slab_block_head_t *)((mem + sizeof(slab_t)) + + (i * (align_size + sizeof(slab_block_head_t)))); + + slab_block->used = 0; + slab_block->magic = SLAB_BLOCK_MAGIC; + slist_init(&slab_block->next); + + slist_add(&tmp_slab->free_block, &slab_block->next); + tmp_slab->free_nr++; + tmp_slab->total_nr++; + } + + return tmp_slab; +} +void slab_release(slab_t *slab) +{ + slab_head_t *slab_head_tmp; + + slist_foreach(slab_head_tmp, &slab->head, next) + { + buddy_free(buddy_get_alloter(), slab_head_tmp->buddy_addr); + } + buddy_free(buddy_get_alloter(), slab); +} + +void *slab_alloc(slab_t *slab) +{ + assert(slab); + mword_t status = spinlock_lock(&slab->lock); + +again: + if (slab->free_nr > 0) + { // 有空闲地则直接分配 + slist_head_t *first = slist_first(&slab->free_block); + + slist_del(first); + slist_add(&slab->used_block, first); + slab_block_head_t *slab_block_free = container_of(first, slab_block_head_t, next); + assert(slab_block_free->magic == SLAB_BLOCK_MAGIC); + slab_block_free->used = 1; + + slab->free_nr--; + spinlock_set(&slab->lock, status); + return (void *)slab_block_free->user_data; + } + else + { + size_t need_size = SLAB_MIN_NUM * (slab->align_size + sizeof(slab_block_head_t)) + sizeof(slab_head_t); + size_t alloc_size = 1 << (is_power_of_2(need_size) ? ffs(need_size) : ffs(need_size) + 1); + if (alloc_size < PAGE_SIZE) + { + alloc_size = PAGE_SIZE; + } + void *mem = buddy_alloc(buddy_get_alloter(), alloc_size); + + if (!mem) + { + spinlock_set(&slab->lock, status); + return NULL; + } + slab_head_t *slab_head = (slab_head_t *)mem; + + slab_head->buddy_addr = mem; + // slab_head->size = alloc_size; + slist_init(&slab_head->next); + slist_add(&slab->head, &slab_head->next); + + for (size_t i = 0; i < alloc_size / (slab->align_size + sizeof(slab_block_head_t)); i++) + { + slab_block_head_t *slab_block = (slab_block_head_t *)((mem + sizeof(slab_head_t)) + + (i * (slab->align_size + sizeof(slab_block_head_t)))); + + slab_block->used = 0; + slab_block->magic = SLAB_BLOCK_MAGIC; + slist_init(&slab_block->next); + + slist_add(&slab->free_block, &slab_block->next); + slab->free_nr++; + slab->total_nr++; + } + goto again; + } + spinlock_set(&slab->lock, status); +} + +void slab_free(slab_t *slab, void *mem) +{ + mword_t status = spinlock_lock(&slab->lock); + + slab_block_head_t *slab_block = container_of(mem, slab_block_head_t, user_data); + + assert(slab_block->magic == SLAB_BLOCK_MAGIC); + assert(slab_block->used); + slab_block->used = 0; + slist_del(&slab_block->next); + slist_add(&slab->free_block, &slab_block->next); + + slab->free_nr++; + spinlock_set(&slab->lock, status); +} + +void slab_print(slab_t *slab) +{ + printk("align size 0x%d, free nr %d, total nr %d\n", slab->align_size, slab->free_nr, slab->total_nr); +} diff --git a/mkrtos_knl/knl/spinlock.c b/mkrtos_knl/knl/spinlock.c index 39887d4a2..54a27f362 100755 --- a/mkrtos_knl/knl/spinlock.c +++ b/mkrtos_knl/knl/spinlock.c @@ -11,6 +11,9 @@ #include "types.h" #include "cpulock.h" #include "spinlock.h" +#include +#include +#include void spinlock_init(spinlock_t *lock) { lock->val &= ~3UL; @@ -31,23 +34,23 @@ mword_t spinlock_lock(spinlock_t *lock) { umword_t status = 0; -#if SMP status = cpulock_lock(); if (spinlock_is_invalidation(lock)) { cpulock_set(status); return -1; } -#else -#error “不支持SMP” +#if CONFIG_SMP + spinlock_lock_arch(lock); + _dmb(ish); #endif return status; } void spinlock_set(spinlock_t *lock, mword_t status) { -#if SMP - cpulock_set(status); -#else -#error “不支持SMP” +#if CONFIG_SMP + _dmb(ish); + spinlock_unlock_arch(lock); #endif + cpulock_set(status); } diff --git a/mkrtos_knl/knl/task.c b/mkrtos_knl/knl/task.c index 24b26777c..57b0aae8f 100755 --- a/mkrtos_knl/knl/task.c +++ b/mkrtos_knl/knl/task.c @@ -38,7 +38,23 @@ enum task_op_code static bool_t task_put(kobject_t *kobj); static void task_release_stage1(kobject_t *kobj); static void task_release_stage2(kobject_t *kobj); +#if IS_ENABLED(CONFIG_BUDDY_SLAB) +#include +static slab_t *task_slab; +#endif +/** + * @brief 在系统初始化时调用,初始化task的内存 + * + */ +static void task_mem_init(void) +{ +#if IS_ENABLED(CONFIG_BUDDY_SLAB) + task_slab = slab_create(sizeof(task_t), "task"); + assert(task_slab); +#endif +} +INIT_KOBJ_MEM(task_mem_init); /** * @brief 为task分配其可以使用的内存空间 * @@ -365,7 +381,12 @@ void task_kill(task_t *tk) } task_t *task_create(ram_limit_t *lim, int is_knl) { - task_t *tk = mm_limit_alloc(lim, sizeof(task_t)); + task_t *tk = NULL; +#if IS_ENABLED(CONFIG_BUDDY_SLAB) + tk = slab_alloc(task_slab); +#else + tk = mm_limit_alloc(lim, sizeof(task_t)); +#endif if (!tk) { diff --git a/mkrtos_knl/knl/thread.c b/mkrtos_knl/knl/thread.c index e07fd09cc..56e24ffa6 100755 --- a/mkrtos_knl/knl/thread.c +++ b/mkrtos_knl/knl/thread.c @@ -76,6 +76,20 @@ static void thread_timeout_init(void) INIT_KOBJ(thread_timeout_init); +#if IS_ENABLED(CONFIG_BUDDY_SLAB) +#include +#endif +/** + * @brief 在系统初始化时调用,初始化thread的内存 + * + */ +static void thread_mem_init(void) +{ +#if IS_ENABLED(CONFIG_BUDDY_SLAB) +#endif +} +INIT_KOBJ_MEM(thread_mem_init); + /** * @brief 线程的初始化函数 * @@ -311,8 +325,13 @@ void thread_todead(thread_t *th, bool_t is_sche) */ thread_t *thread_create(ram_limit_t *ram) { - thread_t *th = mm_limit_alloc_align(ram, THREAD_BLOCK_SIZE, THREAD_BLOCK_SIZE); + thread_t *th = NULL; +#if IS_ENABLED(CONFIG_BUDDY_SLAB) + th = buddy_alloc(buddy_get_alloter(), PAGE_SIZE); +#else + th = mm_limit_alloc_align(ram, THREAD_BLOCK_SIZE, THREAD_BLOCK_SIZE); +#endif if (!th) { return NULL; @@ -567,7 +586,7 @@ static int thread_ipc_reply(msg_tag_t in_tag) } __attribute__((optimize(1))) int thread_ipc_call(thread_t *to_th, msg_tag_t in_tag, msg_tag_t *ret_tag, - ipc_timeout_t timout, umword_t *ret_user_id, bool_t is_call) + ipc_timeout_t timout, umword_t *ret_user_id, bool_t is_call) { int ret = -EINVAL; if (is_call) diff --git a/mkrtos_knl/knl/thread_knl.c b/mkrtos_knl/knl/thread_knl.c index 6f836626b..f166ed30c 100755 --- a/mkrtos_knl/knl/thread_knl.c +++ b/mkrtos_knl/knl/thread_knl.c @@ -107,12 +107,12 @@ static void knl_init_2(void) { mm_trace(); - init_thread = thread_create(&root_factory_get()->limit); assert(init_thread); init_task = task_create(&root_factory_get()->limit, FALSE); assert(init_task); +#if 0 app_info_t *app = app_info_get((void *)(CONFIG_KNL_TEXT_ADDR + CONFIG_INIT_TASK_OFFSET)); // 申请init的ram内存 assert(task_alloc_base_ram(init_task, &root_factory_get()->limit, app->i.ram_size + THREAD_MSG_BUG_LEN) >= 0); @@ -136,6 +136,7 @@ static void knl_init_2(void) init_thread->sche.prio = 2; init_task->pid = 0; thread_ready(init_thread, FALSE); +#endif } INIT_STAGE2(knl_init_2); @@ -161,7 +162,7 @@ void task_knl_kill(thread_t *kill_thread, bool_t is_knl) static void print_mkrtos_info(void) { - const char *start_info[] = { + static const char *start_info[] = { " _____ ______ ___ __ ________ _________ ________ ________ \r\n", "|\\ _ \\ _ \\|\\ \\|\\ \\ |\\ __ \\|\\___ ___\\\\ __ \\|\\ ____\\ \r\n", "\\ \\ \\\\\\__\\ \\ \\ \\ \\/ /|\\ \\ \\|\\ \\|___ \\ \\_\\ \\ \\|\\ \\ \\ \\___|_ \r\n", @@ -187,10 +188,10 @@ void start_kernel(void) printk("mkrtos running..\n"); printk("sys freq:%d\n", arch_get_sys_clk()); print_mkrtos_info(); - sti(); + cli(); sys_startup(); //!< 开始调度 thread_sched(); - cli(); + sti(); while (1) ; diff --git a/mkrtos_knl/lib/CMakeLists.txt b/mkrtos_knl/lib/CMakeLists.txt index 546e1f898..823771007 100755 --- a/mkrtos_knl/lib/CMakeLists.txt +++ b/mkrtos_knl/lib/CMakeLists.txt @@ -6,7 +6,8 @@ add_library(lib STATIC ${deps}) target_include_directories( lib PUBLIC - ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/armv7m/${CONFIG_CPU_TYPE} + ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/${CONFIG_ARCH}/${CONFIG_CPU_TYPE} + ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/${CONFIG_ARCH}/ ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/lib ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/knl ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/drv diff --git a/mkrtos_script/build_f2.sh b/mkrtos_script/build_f2.sh index ef050f57b..8ad0adb41 100755 --- a/mkrtos_script/build_f2.sh +++ b/mkrtos_script/build_f2.sh @@ -2,9 +2,12 @@ # export TOOLCHAIN=/home/zhangzheng/mkrtos-tools/gcc/gcc-arm-none-eabi-5_4-2016q3/bin/ # export TOOLCHAIN_LIB=/home/zhangzheng/mkrtos-tools/gcc/gcc-arm-none-eabi-5_4-2016q3/lib/gcc/arm-none-eabi/5.4.1/armv7-m/ -export TOOLCHAIN=/Users/zhangzheng/gcc-arm-none-eabi-10.3-2021.10/bin/ -export TOOLCHAIN_LIB=/Users/zhangzheng/gcc-arm-none-eabi-10.3-2021.10/lib/gcc/arm-none-eabi/10.3.1/thumb/v7-m/nofp +# export TOOLCHAIN=/Users/zhangzheng/gcc-arm-none-eabi-10.3-2021.10/bin/ +# export TOOLCHAIN_LIB=/Users/zhangzheng/gcc-arm-none-eabi-10.3-2021.10/lib/gcc/arm-none-eabi/10.3.1/thumb/v7-m/nofp +export TOOLCHAIN=/home/zhangzheng/gcc-arm/gcc-arm-none-eabi-10.3-2021.10/bin/ +export TOOLCHAIN_LIB=/home/zhangzheng/gcc-arm/gcc-arm-none-eabi-10.3-2021.10/lib/gcc/arm-none-eabi/10.3.1/thumb/v7-m/nofp export BOARD=STM32F205 +export CROSS_COMPILER=arm-none-eabi- set -e cmake -G Ninja -B build/$KNL . diff --git a/mkrtos_script/build_qemu_aarch64.sh b/mkrtos_script/build_qemu_aarch64.sh new file mode 100755 index 000000000..9f8d0f2c3 --- /dev/null +++ b/mkrtos_script/build_qemu_aarch64.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +export TOOLCHAIN=/home/zhangzheng/gcc-arm-10.3-2021.07-aarch64-aarch64-none-elf/bin/ +export TOOLCHAIN_LIB=/home/zhangzheng/gcc-arm-10.3-2021.07-aarch64-aarch64-none-elf/lib/gcc/aarch64-none-elf/10.3.1 +export BOARD=aarch64_qemu +export CROSS_COMPILER=aarch64-none-elf- + +set -e +cmake -G Ninja -B build/$KNL . +cd build/$KNL && ninja diff --git a/mkrtos_script/debug_aarch64_qemu.sh b/mkrtos_script/debug_aarch64_qemu.sh new file mode 100755 index 000000000..6e286a8ad --- /dev/null +++ b/mkrtos_script/debug_aarch64_qemu.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +if [ -z "$1" ]; then + echo "usage: ./debug.sh [tcp port]" + exit +fi + +# -machine virt,virtualization=on,gic-version=2,highmem=off,secure=off,dumpdtb=virt.dtb +qemu-system-aarch64 \ + -machine virt,virtualization=on,gic-version=2,highmem=off,secure=off\ + -cpu cortex-a53 \ + -nographic \ + -m size=2048 \ + -smp 4\ + -kernel $PWD/build/output/bootstrap.elf \ + -S -gdb tcp::$1 diff --git a/mkrtos_tool/kconfig/__pycache__/kconfigfunctions.cpython-310.pyc b/mkrtos_tool/kconfig/__pycache__/kconfigfunctions.cpython-310.pyc index 5df142d42..db8636ed8 100644 Binary files a/mkrtos_tool/kconfig/__pycache__/kconfigfunctions.cpython-310.pyc and b/mkrtos_tool/kconfig/__pycache__/kconfigfunctions.cpython-310.pyc differ diff --git a/mkrtos_tool/kconfig/__pycache__/kconfiglib.cpython-310.pyc b/mkrtos_tool/kconfig/__pycache__/kconfiglib.cpython-310.pyc index 7a28c5383..14f8b76f4 100644 Binary files a/mkrtos_tool/kconfig/__pycache__/kconfiglib.cpython-310.pyc and b/mkrtos_tool/kconfig/__pycache__/kconfiglib.cpython-310.pyc differ diff --git a/setting.cmake b/setting.cmake index feacd5c06..c29ffd114 100755 --- a/setting.cmake +++ b/setting.cmake @@ -1,5 +1,5 @@ set(CMAKE_TOOLCHAIN_PATH $ENV{TOOLCHAIN} CACHE STRING " " FORCE) -set(CROSS_COMPILE ${CMAKE_TOOLCHAIN_PATH}arm-none-eabi- CACHE PATH "" FORCE) +set(CROSS_COMPILE ${CMAKE_TOOLCHAIN_PATH}$ENV{CROSS_COMPILER} CACHE PATH "" FORCE) set(GCC_LIB_PATH $ENV{TOOLCHAIN_LIB}) set(CMAKE_INSTALL_PATH "${CMAKE_BINARY_DIR}deploy" CACHE PATH "" FORCE) @@ -22,31 +22,16 @@ set(PROJECT_BINARY_DIR ${CMAKE_SOURCE_DIR}/build) set(BOARD $ENV{BOARD}) include(mkrtos_cmake/top.cmake) set(ARCH ${CONFIG_ARCH} CACHE STRING "" FORCE) -message(=======${ARCH}) -message(=======${CONFIG_CPU_TYPE}) +message(======="ARCH=${ARCH}") +message(======="CPU_TYPE=${CONFIG_CPU_TYPE}") # -mfloat-abi=soft -u _printf_float -lc -lrdimon #-mfpu=fpv5-sp-d16 -set(CMAKE_C_FLAGS "-mcpu=${CONFIG_ARCH} -O0 -g3 -mfloat-abi=${CONFIG_FLOAT_TYPE} -mthumb -mno-thumb-interwork -D=MKRTOS \ --std=gnu11 -ffunction-sections -fdata-sections -fno-builtin -u _printf_float \ --nostartfiles -nodefaultlibs -nostdlib -nostdinc -Xlinker \ --fno-stack-protector -Wl,--gc-sections \ --include ${CMAKE_SOURCE_DIR}/build/autoconf.h \ -" CACHE STRING "" FORCE) - -set(CMAKE_CXX_FLAGS "-mcpu=${CONFIG_ARCH} -O2 -g3 -mfloat-abi=${CONFIG_FLOAT_TYPE} -mthumb -mno-thumb-interwork -D=MKRTOS -std=c++11 \ --fmessage-length=0 -Xlinker --print-map -Wall -W -fno-stack-protector -g \ - -u _printf_float \ --ffunction-sections -fdata-sections -fno-builtin -nostartfiles -nodefaultlibs -nostdlib -nostdinc -Xlinker \ --include ${CMAKE_SOURCE_DIR}/build/autoconf.h \ -" CACHE STRING "" FORCE) - -set(CMAKE_ASM_FLAGS "-mcpu=${CONFIG_ARCH} -O2 -g3 -mfloat-abi=${CONFIG_FLOAT_TYPE} -mthumb -mno-thumb-interwork -D=MKRTOS \ --u _printf_float -std=gnu11 -ffunction-sections -fdata-sections -fno-builtin \ --nostartfiles -nodefaultlibs -nostdlib -nostdinc -Xlinker -fno-stack-protector \ --include ${CMAKE_SOURCE_DIR}/build/autoconf.h \ -" CACHE STRING "" FORCE) - +if (${CONFIG_ARCH} STREQUAL "cortex-m3" OR ${CONFIG_ARCH} STREQUAL "cortex-m4") + include(armv7_8.cmake) +elseif(${CONFIG_ARCH} STREQUAL "aarch64" ) + include(aarch64.cmake) +endif() set(CMAKE_C_LINK_EXECUTABLE "${CMAKE_LINKER} --start-group --end-group -o " CACHE INTERNAL " " FORCE) diff --git a/virt.dtb b/virt.dtb new file mode 100644 index 000000000..743311b98 Binary files /dev/null and b/virt.dtb differ diff --git a/virt.dts b/virt.dts new file mode 100644 index 000000000..4290efaba --- /dev/null +++ b/virt.dts @@ -0,0 +1,426 @@ +/dts-v1/; + +/ { + interrupt-parent = <0x8005>; + model = "linux,dummy-virt"; + #size-cells = <0x02>; + #address-cells = <0x02>; + compatible = "linux,dummy-virt"; + + psci { + migrate = <0xc4000005>; + cpu_on = <0xc4000003>; + cpu_off = <0x84000002>; + cpu_suspend = <0xc4000001>; + method = "smc"; + compatible = "arm,psci-1.0\0arm,psci-0.2\0arm,psci"; + }; + + memory@40000000 { + reg = <0x00 0x40000000 0x00 0x80000000>; + device_type = "memory"; + }; + + platform-bus@c000000 { + interrupt-parent = <0x8005>; + ranges = <0x00 0x00 0xc000000 0x2000000>; + #address-cells = <0x01>; + #size-cells = <0x01>; + compatible = "qemu,platform\0simple-bus"; + }; + + fw-cfg@9020000 { + dma-coherent; + reg = <0x00 0x9020000 0x00 0x18>; + compatible = "qemu,fw-cfg-mmio"; + }; + + virtio_mmio@a000000 { + dma-coherent; + interrupts = <0x00 0x10 0x01>; + reg = <0x00 0xa000000 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a000200 { + dma-coherent; + interrupts = <0x00 0x11 0x01>; + reg = <0x00 0xa000200 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a000400 { + dma-coherent; + interrupts = <0x00 0x12 0x01>; + reg = <0x00 0xa000400 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a000600 { + dma-coherent; + interrupts = <0x00 0x13 0x01>; + reg = <0x00 0xa000600 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a000800 { + dma-coherent; + interrupts = <0x00 0x14 0x01>; + reg = <0x00 0xa000800 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a000a00 { + dma-coherent; + interrupts = <0x00 0x15 0x01>; + reg = <0x00 0xa000a00 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a000c00 { + dma-coherent; + interrupts = <0x00 0x16 0x01>; + reg = <0x00 0xa000c00 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a000e00 { + dma-coherent; + interrupts = <0x00 0x17 0x01>; + reg = <0x00 0xa000e00 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a001000 { + dma-coherent; + interrupts = <0x00 0x18 0x01>; + reg = <0x00 0xa001000 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a001200 { + dma-coherent; + interrupts = <0x00 0x19 0x01>; + reg = <0x00 0xa001200 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a001400 { + dma-coherent; + interrupts = <0x00 0x1a 0x01>; + reg = <0x00 0xa001400 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a001600 { + dma-coherent; + interrupts = <0x00 0x1b 0x01>; + reg = <0x00 0xa001600 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a001800 { + dma-coherent; + interrupts = <0x00 0x1c 0x01>; + reg = <0x00 0xa001800 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a001a00 { + dma-coherent; + interrupts = <0x00 0x1d 0x01>; + reg = <0x00 0xa001a00 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a001c00 { + dma-coherent; + interrupts = <0x00 0x1e 0x01>; + reg = <0x00 0xa001c00 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a001e00 { + dma-coherent; + interrupts = <0x00 0x1f 0x01>; + reg = <0x00 0xa001e00 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a002000 { + dma-coherent; + interrupts = <0x00 0x20 0x01>; + reg = <0x00 0xa002000 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a002200 { + dma-coherent; + interrupts = <0x00 0x21 0x01>; + reg = <0x00 0xa002200 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a002400 { + dma-coherent; + interrupts = <0x00 0x22 0x01>; + reg = <0x00 0xa002400 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a002600 { + dma-coherent; + interrupts = <0x00 0x23 0x01>; + reg = <0x00 0xa002600 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a002800 { + dma-coherent; + interrupts = <0x00 0x24 0x01>; + reg = <0x00 0xa002800 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a002a00 { + dma-coherent; + interrupts = <0x00 0x25 0x01>; + reg = <0x00 0xa002a00 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a002c00 { + dma-coherent; + interrupts = <0x00 0x26 0x01>; + reg = <0x00 0xa002c00 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a002e00 { + dma-coherent; + interrupts = <0x00 0x27 0x01>; + reg = <0x00 0xa002e00 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a003000 { + dma-coherent; + interrupts = <0x00 0x28 0x01>; + reg = <0x00 0xa003000 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a003200 { + dma-coherent; + interrupts = <0x00 0x29 0x01>; + reg = <0x00 0xa003200 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a003400 { + dma-coherent; + interrupts = <0x00 0x2a 0x01>; + reg = <0x00 0xa003400 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a003600 { + dma-coherent; + interrupts = <0x00 0x2b 0x01>; + reg = <0x00 0xa003600 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a003800 { + dma-coherent; + interrupts = <0x00 0x2c 0x01>; + reg = <0x00 0xa003800 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a003a00 { + dma-coherent; + interrupts = <0x00 0x2d 0x01>; + reg = <0x00 0xa003a00 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a003c00 { + dma-coherent; + interrupts = <0x00 0x2e 0x01>; + reg = <0x00 0xa003c00 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a003e00 { + dma-coherent; + interrupts = <0x00 0x2f 0x01>; + reg = <0x00 0xa003e00 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + gpio-keys { + compatible = "gpio-keys"; + + poweroff { + gpios = <0x8007 0x03 0x00>; + linux,code = <0x74>; + label = "GPIO Key Poweroff"; + }; + }; + + pl061@9030000 { + phandle = <0x8007>; + clock-names = "apb_pclk"; + clocks = <0x8000>; + interrupts = <0x00 0x07 0x04>; + gpio-controller; + #gpio-cells = <0x02>; + compatible = "arm,pl061\0arm,primecell"; + reg = <0x00 0x9030000 0x00 0x1000>; + }; + + pcie@10000000 { + interrupt-map-mask = <0x1800 0x00 0x00 0x07>; + interrupt-map = <0x00 0x00 0x00 0x01 0x8005 0x00 0x00 0x00 0x03 0x04 0x00 0x00 0x00 0x02 0x8005 0x00 0x00 0x00 0x04 0x04 0x00 0x00 0x00 0x03 0x8005 0x00 0x00 0x00 0x05 0x04 0x00 0x00 0x00 0x04 0x8005 0x00 0x00 0x00 0x06 0x04 0x800 0x00 0x00 0x01 0x8005 0x00 0x00 0x00 0x04 0x04 0x800 0x00 0x00 0x02 0x8005 0x00 0x00 0x00 0x05 0x04 0x800 0x00 0x00 0x03 0x8005 0x00 0x00 0x00 0x06 0x04 0x800 0x00 0x00 0x04 0x8005 0x00 0x00 0x00 0x03 0x04 0x1000 0x00 0x00 0x01 0x8005 0x00 0x00 0x00 0x05 0x04 0x1000 0x00 0x00 0x02 0x8005 0x00 0x00 0x00 0x06 0x04 0x1000 0x00 0x00 0x03 0x8005 0x00 0x00 0x00 0x03 0x04 0x1000 0x00 0x00 0x04 0x8005 0x00 0x00 0x00 0x04 0x04 0x1800 0x00 0x00 0x01 0x8005 0x00 0x00 0x00 0x06 0x04 0x1800 0x00 0x00 0x02 0x8005 0x00 0x00 0x00 0x03 0x04 0x1800 0x00 0x00 0x03 0x8005 0x00 0x00 0x00 0x04 0x04 0x1800 0x00 0x00 0x04 0x8005 0x00 0x00 0x00 0x05 0x04>; + #interrupt-cells = <0x01>; + ranges = <0x1000000 0x00 0x00 0x00 0x3eff0000 0x00 0x10000 0x2000000 0x00 0x10000000 0x00 0x10000000 0x00 0x2eff0000>; + reg = <0x00 0x3f000000 0x00 0x1000000>; + msi-map = <0x00 0x8006 0x00 0x10000>; + dma-coherent; + bus-range = <0x00 0x0f>; + linux,pci-domain = <0x00>; + #size-cells = <0x02>; + #address-cells = <0x03>; + device_type = "pci"; + compatible = "pci-host-ecam-generic"; + }; + + pl031@9010000 { + clock-names = "apb_pclk"; + clocks = <0x8000>; + interrupts = <0x00 0x02 0x04>; + reg = <0x00 0x9010000 0x00 0x1000>; + compatible = "arm,pl031\0arm,primecell"; + }; + + pl011@9000000 { + clock-names = "uartclk\0apb_pclk"; + clocks = <0x8000 0x8000>; + interrupts = <0x00 0x01 0x04>; + reg = <0x00 0x9000000 0x00 0x1000>; + compatible = "arm,pl011\0arm,primecell"; + }; + + pmu { + interrupts = <0x01 0x07 0xf04>; + compatible = "arm,armv8-pmuv3"; + }; + + intc@8000000 { + phandle = <0x8005>; + interrupts = <0x01 0x09 0x04>; + reg = <0x00 0x8000000 0x00 0x10000 0x00 0x8010000 0x00 0x10000 0x00 0x8030000 0x00 0x10000 0x00 0x8040000 0x00 0x10000>; + compatible = "arm,cortex-a15-gic"; + ranges; + #size-cells = <0x02>; + #address-cells = <0x02>; + interrupt-controller; + #interrupt-cells = <0x03>; + + v2m@8020000 { + phandle = <0x8006>; + reg = <0x00 0x8020000 0x00 0x1000>; + msi-controller; + compatible = "arm,gic-v2m-frame"; + }; + }; + + flash@0 { + bank-width = <0x04>; + reg = <0x00 0x00 0x00 0x4000000 0x00 0x4000000 0x00 0x4000000>; + compatible = "cfi-flash"; + }; + + cpus { + #size-cells = <0x00>; + #address-cells = <0x01>; + + cpu-map { + + socket0 { + + cluster0 { + + core0 { + cpu = <0x8004>; + }; + + core1 { + cpu = <0x8003>; + }; + + core2 { + cpu = <0x8002>; + }; + + core3 { + cpu = <0x8001>; + }; + }; + }; + }; + + cpu@0 { + phandle = <0x8004>; + reg = <0x00>; + enable-method = "psci"; + compatible = "arm,cortex-a53"; + device_type = "cpu"; + }; + + cpu@1 { + phandle = <0x8003>; + reg = <0x01>; + enable-method = "psci"; + compatible = "arm,cortex-a53"; + device_type = "cpu"; + }; + + cpu@2 { + phandle = <0x8002>; + reg = <0x02>; + enable-method = "psci"; + compatible = "arm,cortex-a53"; + device_type = "cpu"; + }; + + cpu@3 { + phandle = <0x8001>; + reg = <0x03>; + enable-method = "psci"; + compatible = "arm,cortex-a53"; + device_type = "cpu"; + }; + }; + + timer { + interrupts = <0x01 0x0d 0xf04 0x01 0x0e 0xf04 0x01 0x0b 0xf04 0x01 0x0a 0xf04>; + always-on; + compatible = "arm,armv8-timer\0arm,armv7-timer"; + }; + + apb-pclk { + phandle = <0x8000>; + clock-output-names = "clk24mhz"; + clock-frequency = <0x16e3600>; + #clock-cells = <0x00>; + compatible = "fixed-clock"; + }; + + chosen { + stdout-path = "/pl011@9000000"; + rng-seed = <0x3d77ef5c 0xe9333410 0xb1bb44e9 0xc5c8fed4 0xaa58c7b5 0x6f6a25fd 0xdd2eda37 0xd6e1ece3>; + kaslr-seed = <0x3a9234e7 0x85d9a529>; + }; +};