From: Minep Date: Sat, 19 Aug 2023 22:54:30 +0000 (+0100) Subject: refactor: one more step towards arch-agnostic design X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/commitdiff_plain/1fe5f5eb5378a47bf0f3451762743c162e40faad?hp=b26d3165c52589d1f8de37bf0df27ad96f460f47 refactor: one more step towards arch-agnostic design feat: linker generated array to free up the need of those nasty explicit invocation init_* functions --- diff --git a/lunaix-os/.vscode/c_cpp_properties.json b/lunaix-os/.vscode/c_cpp_properties.json index 7536e26..a2de1fb 100644 --- a/lunaix-os/.vscode/c_cpp_properties.json +++ b/lunaix-os/.vscode/c_cpp_properties.json @@ -10,7 +10,7 @@ ], "compilerArgs": [ "-ffreestanding", - "-D__ARCH_IA32", + "-D__ARCH__=i386", "-D__LUNAIXOS_DEBUG__", "-include flags.h" ], diff --git a/lunaix-os/.vscode/launch.json b/lunaix-os/.vscode/launch.json index 6bbd277..0a866ca 100644 --- a/lunaix-os/.vscode/launch.json +++ b/lunaix-os/.vscode/launch.json @@ -8,7 +8,7 @@ "type": "gdb", "request": "attach", "name": "LunaixOS", - "executable": "${workspaceRoot}/build/bin/lunaix.bin", + "executable": "${workspaceRoot}/build/bin/kernel.bin", "target": ":1234", "remote": true, "cwd": "${workspaceRoot}", diff --git a/lunaix-os/GRUB_TEMPLATE b/lunaix-os/GRUB_TEMPLATE index d2dcc10..7d5fd86 100644 --- a/lunaix-os/GRUB_TEMPLATE +++ b/lunaix-os/GRUB_TEMPLATE @@ -3,4 +3,5 @@ timeout=0 menuentry "$_OS_NAME" { multiboot /boot/kernel.bin + module /boot/modksyms modksyms } \ No newline at end of file diff --git a/lunaix-os/arch/i386/arch.c b/lunaix-os/arch/i386/arch.c new file mode 100644 index 0000000..afdc88c --- /dev/null +++ b/lunaix-os/arch/i386/arch.c @@ -0,0 +1,53 @@ +#include +#include + +#include +#include + +#include +#include + +#include +#include + +void +exception_init() +{ + exception_install_handler(); + isrm_init(); + intr_routine_init(); +} + +extern void +syscall_hndlr(const isr_param* param); + +void +arch_preinit() +{ + exception_init(); + + isrm_bindiv(LUNAIX_SYS_CALL, syscall_hndlr); +} + +struct hwtimer_context* +hwtimer_choose() +{ + struct hwtimer_context* timer; + + timer = apic_hwtimer_context(); + if (timer->supported(timer)) { + return timer; + } + + // TODO select alternatives... + + panick("no timer to use."); +} + +struct hwrtc* +hwrtc_choose() +{ + struct hwrtc* rtc = mc146818a_rtc_context(); + + return rtc; +} \ No newline at end of file diff --git a/lunaix-os/arch/i386/boot/boot.S b/lunaix-os/arch/i386/boot/boot.S index 0ef3fc6..9d75d98 100644 --- a/lunaix-os/arch/i386/boot/boot.S +++ b/lunaix-os/arch/i386/boot/boot.S @@ -9,14 +9,10 @@ .long MB_FLAGS .long CHECKSUM(MB_FLAGS) -.section .hhk_init_bss - .global mb_info - .align 16 - /* 为Multiboot info struct 预留空间 */ - mb_info: - .skip 4096 +.section .boot.bss /* 根据System V ABI,栈地址必须16字节对齐 */ /* 这里只是一个临时栈,在_hhk_init里面我们会初始化内核专用栈 */ + .align 16 stack_bottom: .skip 4096, 0 __stack_top: @@ -35,7 +31,7 @@ .skip KPG_SIZE, 0 -.section .hhk_init_text +.section .boot.text .global start_ .type start_, @function /* Optional, this just give the * linker more knowledge about the label @@ -49,23 +45,20 @@ subl $16, %esp /* - 将咱们的 multiboot_info 挪个地儿,就是上述预留的空间里 - 而后在_hhk_init里,我们会对所有的高半核初始化代码(arch/i386下的所有)进行Identity map - 这样,我们能够保证当分页与虚拟地址开启后,我们的内核能够访问到multiboot info table + parse multiboot struct into arch-agnostic boot info struct */ - movl $mb_info, 4(%esp) movl %ebx, (%esp) - call _save_multiboot_info + call mb_parse /* - _hhk_init用来初始化我们高半核: + kpg_init用来初始化内核页表: 1. 初始化最简单的PD与PT(重新映射我们的内核至3GiB处,以及对相应的地方进行Identity Map) */ movl $(KPG_SIZE), 4(%esp) movl $(_k_ptd - 0xC0000000), (%esp) /* PTD物理地址 */ - call _hhk_init + call kpg_init /* 基本的映射定义好了,我们可以放心的打开分页了 diff --git a/lunaix-os/arch/i386/boot/hhk.c b/lunaix-os/arch/i386/boot/kpt_setup.c similarity index 66% rename from lunaix-os/arch/i386/boot/hhk.c rename to lunaix-os/arch/i386/boot/kpt_setup.c index 0dfe3e2..741731c 100644 --- a/lunaix-os/arch/i386/boot/hhk.c +++ b/lunaix-os/arch/i386/boot/kpt_setup.c @@ -1,7 +1,11 @@ -#include +#define __BOOT_CODE__ + #include #include +#include +#include + #define PT_ADDR(ptd, pt_index) ((ptd_t*)ptd + (pt_index + 1) * 1024) #define SET_PDE(ptd, pde_index, pde) *((ptd_t*)ptd + pde_index) = pde; #define SET_PTE(ptd, pt_index, pte_index, pte) \ @@ -9,8 +13,11 @@ #define sym_val(sym) (ptr_t)(&sym) #define KERNEL_PAGE_COUNT \ - ((sym_val(__kernel_end) - sym_val(__kernel_start) + 0x1000 - 1) >> 12); -#define HHK_PAGE_COUNT ((sym_val(__init_hhk_end) - 0x100000 + 0x1000 - 1) >> 12) + ((sym_val(__kexec_end) - sym_val(__kexec_start) + 0x1000 - 1) >> 12); +#define HHK_PAGE_COUNT \ + ((sym_val(__kexec_boot_end) - 0x100000 + 0x1000 - 1) >> 12) + +#define V2P(vaddr) ((ptr_t)(vaddr)-KERNEL_EXEC) // use table #1 #define PG_TABLE_IDENTITY 0 @@ -23,16 +30,12 @@ #define PG_TABLE_STACK 8 // Provided by linker (see linker.ld) -extern u8_t __kernel_start; -extern u8_t __kernel_end; -extern u8_t __ktext_start; -extern u8_t __ktext_end; - -extern u8_t __init_hhk_end; -extern u8_t _k_stack; +extern u8_t __kexec_start; +extern u8_t __kexec_end; +extern u8_t __kexec_text_start; +extern u8_t __kexec_text_end; -#define boot_text __attribute__((section(".hhk_init_text"))) -#define boot_data __attribute__((section(".hhk_init_data"))) +extern u8_t __kexec_boot_end; void boot_text _init_page(x86_page_table* ptd) @@ -60,8 +63,8 @@ _init_page(x86_page_table* ptd) // 这里是一些计算,主要是计算应当映射进的 页目录 与 页表 的条目索引(Entry // Index) - u32_t kernel_pde_index = L1_INDEX(sym_val(__kernel_start)); - u32_t kernel_pte_index = L2_INDEX(sym_val(__kernel_start)); + u32_t kernel_pde_index = L1_INDEX(sym_val(__kexec_start)); + u32_t kernel_pte_index = L2_INDEX(sym_val(__kexec_start)); u32_t kernel_pg_counts = KERNEL_PAGE_COUNT; // 将内核所需要的页表注册进页目录 @@ -81,9 +84,9 @@ _init_page(x86_page_table* ptd) } // 计算内核.text段的物理地址 - ptr_t kernel_pm = V2P(&__kernel_start); - ptr_t ktext_start = V2P(&__ktext_start); - ptr_t ktext_end = V2P(&ktext_end); + ptr_t kernel_pm = V2P(&__kexec_start); + ptr_t ktext_start = V2P(&__kexec_text_start); + ptr_t ktext_end = V2P(&__kexec_text_end); // 重映射内核至高半区地址(>=0xC0000000) for (u32_t i = 0; i < kernel_pg_counts; i++) { @@ -104,39 +107,8 @@ _init_page(x86_page_table* ptd) ptd->entry[PG_MAX_ENTRIES - 1] = NEW_L1_ENTRY(T_SELF_REF_PERM, ptd); } -u32_t boot_text -__save_subset(u8_t* destination, u8_t* base, unsigned int size) -{ - unsigned int i = 0; - for (; i < size; i++) { - *(destination + i) = *(base + i); - } - return i; -} - -void boot_text -_save_multiboot_info(multiboot_info_t* info, u8_t* destination) -{ - u32_t current = 0; - u8_t* info_b = (u8_t*)info; - for (; current < sizeof(multiboot_info_t); current++) { - *(destination + current) = *(info_b + current); - } - - ((multiboot_info_t*)destination)->mmap_addr = (ptr_t)destination + current; - current += __save_subset( - destination + current, (u8_t*)info->mmap_addr, info->mmap_length); - - if (present(info->flags, MULTIBOOT_INFO_DRIVE_INFO)) { - ((multiboot_info_t*)destination)->drives_addr = - (ptr_t)destination + current; - current += __save_subset( - destination + current, (u8_t*)info->drives_addr, info->drives_length); - } -} - void boot_text -_hhk_init(x86_page_table* ptd, u32_t kpg_size) +kpg_init(x86_page_table* ptd, u32_t kpg_size) { // 初始化 kpg 全为0 diff --git a/lunaix-os/arch/i386/boot/mb_parser.c b/lunaix-os/arch/i386/boot/mb_parser.c new file mode 100644 index 0000000..81e2716 --- /dev/null +++ b/lunaix-os/arch/i386/boot/mb_parser.c @@ -0,0 +1,194 @@ +#define __BOOT_CODE__ + +#include +#include +#include +#include + +#define BHCTX_ALLOC 4096 + +u8_t bhctx_buffer[BHCTX_ALLOC] boot_bss; + +#define check_buffer(ptr) \ + if ((ptr) >= ((ptr_t)bhctx_buffer + BHCTX_ALLOC)) { \ + asm("ud2"); \ + } + +size_t boot_text +mb_memcpy(u8_t* destination, u8_t* base, unsigned int size) +{ + unsigned int i = 0; + for (; i < size; i++) { + *(destination + i) = *(base + i); + } + return i; +} + +size_t boot_text +mb_strcpy(char* destination, char* base) +{ + int i = 0; + char c = 0; + while ((c = base[i])) { + destination[i] = c; + i++; + } + + destination[++i] = 0; + + return i; +} + +size_t boot_text +mb_strlen(char* s) +{ + int i = 0; + while (s[i++]) + ; + return i; +} + +size_t boot_text +mb_parse_cmdline(struct boot_handoff* bhctx, void* buffer, char* cmdline) +{ +#define SPACE ' ' + + size_t slen = mb_strlen(cmdline); + + if (!slen) { + return 0; + } + + mb_memcpy(buffer, (u8_t*)cmdline, slen); + + cmdline = (char*)buffer; + buffer = &cmdline[slen]; + + char c, prev = SPACE; + int i = 0, argc = 0; + ptr_t argptr = (ptr_t)cmdline; + + while ((c = cmdline[i])) { + if (c == SPACE && prev != SPACE) { + ((ptr_t*)buffer)[argc++] = argptr; + } else if (c != SPACE && prev == SPACE) { + argptr = (ptr_t)&cmdline[i]; + } + prev = c; + i++; + } + + bhctx->kexec.argv = (char**)buffer; + bhctx->kexec.argc = argc; + + return slen + argc * sizeof(ptr_t); +} + +size_t boot_text +mb_parse_mmap(struct boot_handoff* bhctx, + struct multiboot_info* mb, + void* buffer) +{ + struct multiboot_mmap_entry* mb_mmap = + (struct multiboot_mmap_entry*)mb->mmap_addr; + size_t mmap_len = mb->mmap_length / sizeof(struct multiboot_mmap_entry); + + struct boot_mmapent* bmmap = (struct boot_mmapent*)buffer; + for (size_t i = 0; i < mmap_len; i++) { + struct boot_mmapent* bmmapent = &bmmap[i]; + struct multiboot_mmap_entry* mb_mapent = &mb_mmap[i]; + + if (mb_mapent->type == MULTIBOOT_MEMORY_AVAILABLE) { + bmmapent->type = BOOT_MMAP_FREE; + } else if (mb_mapent->type == MULTIBOOT_MEMORY_ACPI_RECLAIMABLE) { + bmmapent->type = BOOT_MMAP_RCLM; + } else { + bmmapent->type = BOOT_MMAP_RSVD; + } + + bmmapent->start = mb_mapent->addr_low; + bmmapent->size = mb_mapent->len_low; + } + + bhctx->mem.size = (mb->mem_upper << 10) + MEM_1M; + bhctx->mem.mmap = bmmap; + bhctx->mem.mmap_len = mmap_len; + + return mmap_len * sizeof(struct boot_mmapent); +} + +size_t boot_text +mb_parse_mods(struct boot_handoff* bhctx, + struct multiboot_info* mb, + void* buffer) +{ + if (!mb->mods_count) { + bhctx->mods.mods_num = 0; + return 0; + } + + struct boot_modent* modents = (struct boot_modent*)buffer; + struct multiboot_mod_list* mods = (struct multiboot_mod_list*)mb->mods_addr; + + ptr_t mod_str_ptr = (ptr_t)&modents[mb->mods_count]; + + for (size_t i = 0; i < mb->mods_count; i++) { + struct multiboot_mod_list* mod = &mods[i]; + modents[i] = (struct boot_modent){ .start = mod->mod_start, + .end = mod->mod_end, + .str = (char*)mod_str_ptr }; + mod_str_ptr += mb_strcpy((char*)mod_str_ptr, (char*)mod->cmdline); + } + + bhctx->mods.mods_num = mb->mods_count; + bhctx->mods.entries = modents; + + return mod_str_ptr - (ptr_t)buffer; +} + +void boot_text +mb_prepare_hook(struct boot_handoff* bhctx) +{ + // nothing to do +} + +void boot_text +mb_release_hook(struct boot_handoff* bhctx) +{ + // nothing to do +} + +#define align_addr(addr) (((addr) + (sizeof(ptr_t) - 1)) & ~(sizeof(ptr_t) - 1)) + +struct boot_handoff* boot_text +mb_parse(struct multiboot_info* mb) +{ + struct boot_handoff* bhctx = (struct boot_handoff*)bhctx_buffer; + ptr_t bhctx_ex = (ptr_t)&bhctx[1]; + + /* Parse memory map */ + if ((mb->flags & MULTIBOOT_INFO_MEM_MAP)) { + bhctx_ex += mb_parse_mmap(bhctx, mb, (void*)bhctx_ex); + bhctx_ex = align_addr(bhctx_ex); + } + + /* Parse cmdline */ + if ((mb->flags & MULTIBOOT_INFO_CMDLINE)) { + bhctx_ex += + mb_parse_cmdline(bhctx, (void*)bhctx_ex, (char*)mb->cmdline); + bhctx_ex = align_addr(bhctx_ex); + } + + /* Parse sys modules */ + if ((mb->flags & MULTIBOOT_INFO_MODS)) { + bhctx_ex += mb_parse_mods(bhctx, mb, (void*)bhctx_ex); + bhctx_ex = align_addr(bhctx_ex); + } + + check_buffer(bhctx_ex); + + bhctx->prepare = mb_prepare_hook; + bhctx->release = mb_release_hook; + + return bhctx; +} \ No newline at end of file diff --git a/lunaix-os/arch/i386/boot/prologue.S b/lunaix-os/arch/i386/boot/prologue.S index 7a51648..ff77ef5 100644 --- a/lunaix-os/arch/i386/boot/prologue.S +++ b/lunaix-os/arch/i386/boot/prologue.S @@ -1,7 +1,7 @@ /* 高半核入口点 - 0xC0000000 */ #define __ASM__ -#include +#include .section .text .global hhk_entry_ @@ -9,7 +9,7 @@ /* 欢迎来到虚拟内存的世界! :D */ - + andl $stack_alignment, %esp subl $16, %esp /* 最终还是决定将IDT&GDT的初始化和安装放在这里 @@ -21,6 +21,7 @@ 这主要是为了保险起见,让GDTR有一个合法的值,否则多咱的粗心大意,容易出#GP */ call _init_gdt + movl $_gdt, 2(%esp) movw _gdt_limit, %ax movw %ax, (%esp) @@ -33,19 +34,14 @@ movw %cx, %fs movw %cx, %gs movw %cx, %ss - + /* 更新 CS:EIP */ pushw $KCODE_SEG pushl $_after_gdt retf _after_gdt: - - movl $mb_info, _k_init_mb_info - - call _kernel_pre_init - - subl $6, %esp + subl $16, %esp # 加载 IDT movl $_idt, 2(%esp) @@ -53,13 +49,15 @@ movw %ax, (%esp) lidt (%esp) + # perform arch-specific initialization before diving into kernel + call arch_preinit + /* 加载TSS段选择器 */ movw $TSS_SEG, %ax ltr %ax - addl $6, %esp - - call _kernel_init + movl $bhctx_buffer, (%esp) # mb_parser.c + call kernel_bootstrap 1: hlt diff --git a/lunaix-os/arch/i386/exceptions/gdt.h b/lunaix-os/arch/i386/exceptions/gdt.h deleted file mode 100644 index f312166..0000000 --- a/lunaix-os/arch/i386/exceptions/gdt.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef __LUNAIX_GDT_H -#define __LUNAIX_GDT_H 1 - -#define SD_TYPE(x) (x << 8) -#define SD_CODE_DATA(x) (x << 12) -#define SD_DPL(x) (x << 13) -#define SD_PRESENT(x) (x << 15) -#define SD_AVL(x) (x << 20) -#define SD_64BITS(x) (x << 21) -#define SD_32BITS(x) (x << 22) -#define SD_4K_GRAN(x) (x << 23) - -#define SEG_LIM_L(x) (x & 0x0ffff) -#define SEG_LIM_H(x) (x & 0xf0000) -#define SEG_BASE_L(x) ((x & 0x0000ffff) << 16) -#define SEG_BASE_M(x) ((x & 0x00ff0000) >> 16) -#define SEG_BASE_H(x) (x & 0xff000000) - -#define SEG_DATA_RD 0x00 // Read-Only -#define SEG_DATA_RDA 0x01 // Read-Only, accessed -#define SEG_DATA_RDWR 0x02 // Read/Write -#define SEG_DATA_RDWRA 0x03 // Read/Write, accessed -#define SEG_DATA_RDEXPD 0x04 // Read-Only, expand-down -#define SEG_DATA_RDEXPDA 0x05 // Read-Only, expand-down, accessed -#define SEG_DATA_RDWREXPD 0x06 // Read/Write, expand-down -#define SEG_DATA_RDWREXPDA 0x07 // Read/Write, expand-down, accessed -#define SEG_CODE_EX 0x08 // Execute-Only -#define SEG_CODE_EXA 0x09 // Execute-Only, accessed -#define SEG_CODE_EXRD 0x0A // Execute/Read -#define SEG_CODE_EXRDA 0x0B // Execute/Read, accessed -#define SEG_CODE_EXC 0x0C // Execute-Only, conforming -#define SEG_CODE_EXCA 0x0D // Execute-Only, conforming, accessed -#define SEG_CODE_EXRDC 0x0E // Execute/Read, conforming -#define SEG_CODE_EXRDCA 0x0F // Execute/Read, conforming, accessed - -#define SEG_R0_CODE SD_TYPE(SEG_CODE_EXRD) | SD_CODE_DATA(1) | SD_DPL(0) | \ - SD_PRESENT(1) | SD_AVL(0) | SD_64BITS(0) | SD_32BITS(1) | \ - SD_4K_GRAN(1) - -#define SEG_R0_DATA SD_TYPE(SEG_DATA_RDWR) | SD_CODE_DATA(1) | SD_DPL(0) | \ - SD_PRESENT(1) | SD_AVL(0) | SD_64BITS(0) | SD_32BITS(1) | \ - SD_4K_GRAN(1) - -#define SEG_R3_CODE SD_TYPE(SEG_CODE_EXRD) | SD_CODE_DATA(1) | SD_DPL(3) | \ - SD_PRESENT(1) | SD_AVL(0) | SD_64BITS(0) | SD_32BITS(1) | \ - SD_4K_GRAN(1) - -#define SEG_R3_DATA SD_TYPE(SEG_DATA_RDWR) | SD_CODE_DATA(1) | SD_DPL(3) | \ - SD_PRESENT(1) | SD_AVL(0) | SD_64BITS(0) | SD_32BITS(1) | \ - SD_4K_GRAN(1) - -#define SEG_TSS SD_TYPE(9) | SD_DPL(0) | SD_PRESENT(1) - - -void -_init_gdt(); - -#endif diff --git a/lunaix-os/arch/i386/exceptions/i386_isrdef.c b/lunaix-os/arch/i386/exceptions/i386_isrdef.c index 81a4d34..8bebb96 100644 --- a/lunaix-os/arch/i386/exceptions/i386_isrdef.c +++ b/lunaix-os/arch/i386/exceptions/i386_isrdef.c @@ -1,7 +1,7 @@ /* Generated from i386_isrdef.c.j2. Do NOT modify */ -#include "i386_intr.h" #include +#include #define IDT_INTERRUPT 0x70 #define KERNEL_CS 0x8 diff --git a/lunaix-os/arch/i386/exceptions/i386_isrm.c b/lunaix-os/arch/i386/exceptions/i386_isrm.c index a45ce7e..1d5950e 100644 --- a/lunaix-os/arch/i386/exceptions/i386_isrm.c +++ b/lunaix-os/arch/i386/exceptions/i386_isrm.c @@ -1,9 +1,8 @@ -#include -#include - #include #include +#include + /* total: 256 ivs 0~31: reserved for sys use (x32) @@ -11,8 +10,8 @@ 48~ : free to allocate for external hardware use. (x208) */ -static char iv_bmp[(IV_MAX - IV_BASE) / 8]; -static isr_cb handlers[IV_MAX]; +static char iv_bmp[(IV_EX_END - IV_BASE_END) / 8]; +static isr_cb handlers[TOTAL_IV]; extern void intr_routine_fallback(const isr_param* param); @@ -20,7 +19,7 @@ intr_routine_fallback(const isr_param* param); void isrm_init() { - for (size_t i = 0; i < 256; i++) { + for (size_t i = 0; i < TOTAL_IV; i++) { handlers[i] = intr_routine_fallback; } } @@ -28,23 +27,31 @@ isrm_init() static inline int __ivalloc_within(size_t a, size_t b, isr_cb handler) { - a = (a - IV_BASE) / 8; - b = (b - IV_BASE) / 8; + a = (a - IV_BASE_END); + b = (b - IV_BASE_END); + u8_t j = a % 8; + u8_t k = 0; - for (size_t i = a; i < b; i++) { - u8_t chunk = iv_bmp[i], j = 0; + for (size_t i = a / 8; i < b / 8; i++, k += 8) { + u8_t chunk = iv_bmp[i]; if (chunk == 0xff) continue; - while ((chunk & 0x1)) { + chunk >>= j; + while ((chunk & 0x1) && k <= b) { chunk >>= 1; j++; + k++; + } + + if (k > b) { + break; } iv_bmp[i] |= 1 << j; - int iv = IV_BASE + i * 8 + j; + int iv = IV_BASE_END + i * 8 + j; handlers[iv] = handler ? handler : intr_routine_fallback; return iv; @@ -56,13 +63,13 @@ __ivalloc_within(size_t a, size_t b, isr_cb handler) int isrm_ivosalloc(isr_cb handler) { - return __ivalloc_within(IV_BASE, IV_EX, handler); + return __ivalloc_within(IV_BASE_END, IV_EX_BEGIN, handler); } int isrm_ivexalloc(isr_cb handler) { - return __ivalloc_within(IV_EX, IV_MAX, handler); + return __ivalloc_within(IV_EX_BEGIN, IV_EX_END, handler); } void @@ -70,8 +77,8 @@ isrm_ivfree(int iv) { assert(iv < 256); - if (iv >= IV_BASE) { - iv_bmp[(iv - IV_BASE) / 8] &= ~(1 << ((iv - IV_BASE) % 8)); + if (iv >= IV_BASE_END) { + iv_bmp[(iv - IV_BASE_END) / 8] &= ~(1 << ((iv - IV_BASE_END) % 8)); } handlers[iv] = intr_routine_fallback; @@ -86,9 +93,8 @@ isrm_bindirq(int irq, isr_cb irq_handler) return 0; // never reach } - // PC_AT_IRQ_RTC -> RTC_TIMER_IV, fixed, edge trigged, polarity=high, - // physical, APIC ID 0 - ioapic_redirect(acpi_gistranslate(irq), iv, 0, IOAPIC_DELMOD_FIXED); + // fixed, edge trigged, polarity=high + intc_irq_attach(irq, iv, 0, IRQ_DEFAULT); return iv; } @@ -98,8 +104,8 @@ isrm_bindiv(int iv, isr_cb handler) { assert(iv < 256); - if (iv >= IV_BASE) { - iv_bmp[(iv - IV_BASE) / 8] |= 1 << ((iv - IV_BASE) % 8); + if (iv >= IV_BASE_END) { + iv_bmp[(iv - IV_BASE_END) / 8] |= 1 << ((iv - IV_BASE_END) % 8); } handlers[iv] = handler; diff --git a/lunaix-os/arch/i386/exceptions/interrupt.S b/lunaix-os/arch/i386/exceptions/interrupt.S index d2f5543..e5a125f 100644 --- a/lunaix-os/arch/i386/exceptions/interrupt.S +++ b/lunaix-os/arch/i386/exceptions/interrupt.S @@ -163,7 +163,7 @@ # 约定 # arg1: 目标进程PCB地址 (next - popl %ebx # next + movl %eax, %ebx # next movl __current, %eax movl proc_page_table(%eax), %ecx # __current->pagetable movl proc_page_table(%ebx), %eax # next->pagetable @@ -184,7 +184,14 @@ test %eax, %eax # do we have signal to handle? jz 1f - # 更新 tss + /* + 将tss.esp0设置为上次调度前的esp值。 + 当处理信号时,上下文信息是不会恢复的,而是保存在用户栈中,然后直接跳转进位于用户空间的sig_wrapper进行 + 信号的处理。当用户自定义的信号处理函数返回时,sigreturn的系统调用才开始进行上下文的恢复(或者说是进行 + 另一次调度。 + 由于这中间没有进行地址空间的交换,所以第二次跳转使用的是同一个内核栈,而之前默认tss.esp0的值是永远指向最顶部 + 这样一来就有可能会覆盖更早的上下文信息(比如嵌套的信号捕获函数) + */ movl proc_intr_ctx(%ebx), %ecx # __current->intr_ctx movl %ecx, (tss_esp0_off + _tss) diff --git a/lunaix-os/arch/i386/exceptions/interrupts.c b/lunaix-os/arch/i386/exceptions/interrupts.c index cea822d..adde973 100644 --- a/lunaix-os/arch/i386/exceptions/interrupts.c +++ b/lunaix-os/arch/i386/exceptions/interrupts.c @@ -1,8 +1,8 @@ #include #include -#include #include +#include #include #include @@ -12,20 +12,10 @@ #include #include -#include "i386_intr.h" +#include LOG_MODULE("INTR") -extern x86_page_table* __kernel_ptd; - -void -exception_init() -{ - exception_install_handler(); - isrm_init(); - intr_routine_init(); -} - void intr_handler(isr_param* param) { @@ -47,11 +37,8 @@ intr_handler(isr_param* param) execp->eip); done: - // for all external interrupts except the spurious interrupt - // this is required by Intel Manual Vol.3A, section 10.8.1 & 10.8.5 - if (execp->vector >= IV_EX && execp->vector != APIC_SPIV_IV) { - apic_done_servicing(); - } + + intc_notify_eoi(0, execp->vector); return; } \ No newline at end of file diff --git a/lunaix-os/arch/i386/exceptions/intr_routines.c b/lunaix-os/arch/i386/exceptions/intr_routines.c index 8afd22a..6571f9a 100644 --- a/lunaix-os/arch/i386/exceptions/intr_routines.c +++ b/lunaix-os/arch/i386/exceptions/intr_routines.c @@ -10,9 +10,8 @@ #include -#include - -#include "i386_intr.h" +#include +#include LOG_MODULE("INTR") @@ -64,8 +63,8 @@ intr_routine_sys_panic(const isr_param* param) void intr_routine_fallback(const isr_param* param) { - console_flush(); __print_panic_msg("Unknown Interrupt", param); + console_flush(); spin(); } diff --git a/lunaix-os/arch/i386/gdt.c b/lunaix-os/arch/i386/gdt.c deleted file mode 100644 index 7f31c9a..0000000 --- a/lunaix-os/arch/i386/gdt.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "gdt.h" -#include -#include - -#define GDT_ENTRY 6 - -u64_t _gdt[GDT_ENTRY]; -u16_t _gdt_limit = sizeof(_gdt) - 1; - -void -_set_gdt_entry(u32_t index, u32_t base, u32_t limit, u32_t flags) -{ - _gdt[index] = - SEG_BASE_H(base) | flags | SEG_LIM_H(limit) | SEG_BASE_M(base); - _gdt[index] <<= 32; - _gdt[index] |= SEG_BASE_L(base) | SEG_LIM_L(limit); -} - -extern struct x86_tss _tss; - -void -_init_gdt() -{ - _set_gdt_entry(0, 0, 0, 0); - _set_gdt_entry(1, 0, 0xfffff, SEG_R0_CODE); - _set_gdt_entry(2, 0, 0xfffff, SEG_R0_DATA); - _set_gdt_entry(3, 0, 0xfffff, SEG_R3_CODE); - _set_gdt_entry(4, 0, 0xfffff, SEG_R3_DATA); - _set_gdt_entry(5, (u32_t)&_tss, sizeof(struct x86_tss) - 1, SEG_TSS); -} \ No newline at end of file diff --git a/lunaix-os/hal/apic.c b/lunaix-os/arch/i386/hal/apic.c similarity index 88% rename from lunaix-os/hal/apic.c rename to lunaix-os/arch/i386/hal/apic.c index 099fd50..bd53fc5 100644 --- a/lunaix-os/hal/apic.c +++ b/lunaix-os/arch/i386/hal/apic.c @@ -8,20 +8,22 @@ * @copyright Copyright (c) 2022 * */ -#include + #include -#include -#include +#include +#include #include #include #include #include +#include "pic.h" + LOG_MODULE("APIC") -static volatile uintptr_t _apic_base; +static volatile ptr_t _apic_base; void apic_setup_lvts(); @@ -100,9 +102,13 @@ apic_setup_lvts() } void -apic_done_servicing() +apic_on_eoi(struct intc_context* intc_ctx, cpu_t cpu, int iv) { - *(unsigned int*)(_apic_base + APIC_EOI) = 0; + // for all external interrupts except the spurious interrupt + // this is required by Intel Manual Vol.3A, section 10.8.1 & 10.8.5 + if (iv >= IV_EX_BEGIN && iv != APIC_SPIV_IV) { + *(unsigned int*)(_apic_base + APIC_EOI) = 0; + } } unsigned int diff --git a/lunaix-os/arch/i386/hal/ioapic.c b/lunaix-os/arch/i386/hal/ioapic.c new file mode 100644 index 0000000..5d233f4 --- /dev/null +++ b/lunaix-os/arch/i386/hal/ioapic.c @@ -0,0 +1,90 @@ +#include +#include + +#include +#include + +#include +#include + +#define IOAPIC_IOREGSEL 0x00 +#define IOAPIC_IOWIN 0x10 +#define IOAPIC_IOREDTBL_BASE 0x10 + +#define IOAPIC_REG_ID 0x00 +#define IOAPIC_REG_VER 0x01 +#define IOAPIC_REG_ARB 0x02 + +#define IOAPIC_DELMOD_FIXED 0b000 +#define IOAPIC_DELMOD_LPRIO 0b001 +#define IOAPIC_DELMOD_NMI 0b100 + +#define IOAPIC_MASKED (1 << 16) +#define IOAPIC_TRIG_LEVEL (1 << 15) +#define IOAPIC_INTPOL_L (1 << 13) +#define IOAPIC_DESTMOD_LOGIC (1 << 11) + +#define IOAPIC_BASE_VADDR 0x2000 + +#define IOAPIC_REG_SEL *((volatile u32_t*)(_ioapic_base + IOAPIC_IOREGSEL)) +#define IOAPIC_REG_WIN *((volatile u32_t*)(_ioapic_base + IOAPIC_IOWIN)) + +static volatile ptr_t _ioapic_base; + +void +ioapic_init() +{ + // Remapping the IRQs + + acpi_context* acpi_ctx = acpi_get_context(); + + _ioapic_base = + (ptr_t)ioremap(acpi_ctx->madt.ioapic->ioapic_addr & ~0xfff, 4096); +} + +void +ioapic_write(u8_t sel, u32_t val) +{ + IOAPIC_REG_SEL = sel; + IOAPIC_REG_WIN = val; +} + +u32_t +ioapic_read(u8_t sel) +{ + IOAPIC_REG_SEL = sel; + return IOAPIC_REG_WIN; +} + +void +ioapic_irq_remap(struct intc_context*, int irq, int iv, cpu_t dest, u32_t flags) +{ + /* + FIXME move it to HAL level. since every platform might have their own + wiring, thus gsi mapping is required all the time + */ + irq = acpi_gsimap(irq); + u8_t reg_sel = IOAPIC_IOREDTBL_BASE + irq * 2; + + u32_t ioapic_fg = 0; + + if ((flags & IRQ_TYPE) == IRQ_TYPE_FIXED) { + ioapic_fg |= IOAPIC_DELMOD_FIXED; + } else { + ioapic_fg |= IOAPIC_DELMOD_NMI; + } + + if ((flags & IRQ_TRIG_LEVEL)) { + ioapic_fg |= IOAPIC_TRIG_LEVEL; + } + + if (!(flags & IRQ_VE_HI)) { + ioapic_fg |= IOAPIC_INTPOL_L; + } + + // Write low 32 bits + ioapic_write(reg_sel, (iv | ioapic_fg) & 0x1FFFF); + + // Write high 32 bits + ioapic_write(reg_sel + 1, (dest << 24)); +} \ No newline at end of file diff --git a/lunaix-os/arch/i386/hal/pci_hba.c b/lunaix-os/arch/i386/hal/pci_hba.c new file mode 100644 index 0000000..60e3db8 --- /dev/null +++ b/lunaix-os/arch/i386/hal/pci_hba.c @@ -0,0 +1,32 @@ +#include +#include + +void +pci_setup_msi(struct pci_device* device, int vector) +{ + // Dest: APIC#0, Physical Destination, No redirection + u32_t msi_addr = (__APIC_BASE_PADDR); + + // Edge trigger, Fixed delivery + u32_t msi_data = vector; + + pci_write_cspace( + device->cspace_base, PCI_MSI_ADDR(device->msi_loc), msi_addr); + + pci_reg_t reg1 = pci_read_cspace(device->cspace_base, device->msi_loc); + pci_reg_t msg_ctl = reg1 >> 16; + + int offset = !!(msg_ctl & MSI_CAP_64BIT) * 4; + pci_write_cspace(device->cspace_base, + PCI_MSI_DATA(device->msi_loc, offset), + msi_data & 0xffff); + + if ((msg_ctl & MSI_CAP_MASK)) { + pci_write_cspace( + device->cspace_base, PCI_MSI_MASK(device->msi_loc, offset), 0); + } + + // manipulate the MSI_CTRL to allow device using MSI to request service. + reg1 = (reg1 & 0xff8fffff) | 0x10000; + pci_write_cspace(device->cspace_base, device->msi_loc, reg1); +} \ No newline at end of file diff --git a/lunaix-os/includes/hal/pic.h b/lunaix-os/arch/i386/hal/pic.h similarity index 100% rename from lunaix-os/includes/hal/pic.h rename to lunaix-os/arch/i386/hal/pic.h diff --git a/lunaix-os/arch/i386/hal/x86_intc.c b/lunaix-os/arch/i386/hal/x86_intc.c new file mode 100644 index 0000000..948eeca --- /dev/null +++ b/lunaix-os/arch/i386/hal/x86_intc.c @@ -0,0 +1,16 @@ +#include +#include +#include + +extern struct intc_context arch_intc_ctx; + +void +intc_init() +{ + apic_init(); + ioapic_init(); + + arch_intc_ctx.name = "i386_apic"; + arch_intc_ctx.irq_attach = ioapic_irq_remap; + arch_intc_ctx.notify_eoi = apic_on_eoi; +} diff --git a/lunaix-os/arch/i386/includes/sys/abi.h b/lunaix-os/arch/i386/includes/sys/abi.h index f610b93..482d6f1 100644 --- a/lunaix-os/arch/i386/includes/sys/abi.h +++ b/lunaix-os/arch/i386/includes/sys/abi.h @@ -31,6 +31,8 @@ "r"(pc) \ : "eax", "memory"); +#define switch_context(process) asm volatile("jmp switch_to\n" ::"a"(process)); + #define push_arg1(stack_ptr, arg) *((typeof((arg))*)(stack_ptr)--) = arg #define push_arg2(stack_ptr, arg1, arg2) \ { \ diff --git a/lunaix-os/includes/hal/apic.h b/lunaix-os/arch/i386/includes/sys/apic.h similarity index 93% rename from lunaix-os/includes/hal/apic.h rename to lunaix-os/arch/i386/includes/sys/apic.h index a4ac95f..ce62af2 100644 --- a/lunaix-os/includes/hal/apic.h +++ b/lunaix-os/arch/i386/includes/sys/apic.h @@ -1,8 +1,9 @@ #ifndef __LUNAIX_APIC_H #define __LUNAIX_APIC_H +#include #include -#include +#include #define __APIC_BASE_PADDR 0xFEE00000 @@ -75,12 +76,7 @@ apic_write_reg(unsigned int reg, unsigned int val); void apic_init(); -/** - * @brief Tell the APIC that the handler for current interrupt is finished. - * This will issue a write action to EOI register. - * - */ void -apic_done_servicing(); +apic_on_eoi(struct intc_context* intc_ctx, cpu_t cpu, int iv); #endif /* __LUNAIX_APIC_H */ diff --git a/lunaix-os/arch/i386/includes/sys/boot/bstage.h b/lunaix-os/arch/i386/includes/sys/boot/bstage.h new file mode 100644 index 0000000..0744481 --- /dev/null +++ b/lunaix-os/arch/i386/includes/sys/boot/bstage.h @@ -0,0 +1,8 @@ +#ifndef __LUNAIX_BSTAGE_H +#define __LUNAIX_BSTAGE_H + +#define boot_text __attribute__((section(".boot.text"))) +#define boot_data __attribute__((section(".boot.data"))) +#define boot_bss __attribute__((section(".boot.bss"))) + +#endif /* __LUNAIX_BSTAGE_H */ diff --git a/lunaix-os/arch/i386/exceptions/i386_intr.h b/lunaix-os/arch/i386/includes/sys/i386_intr.h similarity index 100% rename from lunaix-os/arch/i386/exceptions/i386_intr.h rename to lunaix-os/arch/i386/includes/sys/i386_intr.h diff --git a/lunaix-os/arch/i386/includes/sys/ioapic.h b/lunaix-os/arch/i386/includes/sys/ioapic.h new file mode 100644 index 0000000..0c97528 --- /dev/null +++ b/lunaix-os/arch/i386/includes/sys/ioapic.h @@ -0,0 +1,16 @@ +#ifndef __LUNAIX_IOAPIC_H +#define __LUNAIX_IOAPIC_H + +#include + +void +ioapic_init(); + +void +ioapic_irq_remap(struct intc_context*, + int irq, + int iv, + cpu_t dest, + u32_t flags); + +#endif /* __LUNAIX_IOAPIC_H */ diff --git a/lunaix-os/arch/i386/includes/sys/mm/mempart.h b/lunaix-os/arch/i386/includes/sys/mm/mempart.h index 50015aa..33d5c8b 100644 --- a/lunaix-os/arch/i386/includes/sys/mm/mempart.h +++ b/lunaix-os/arch/i386/includes/sys/mm/mempart.h @@ -1,3 +1,5 @@ +#ifndef __LUNAIX_MEMPART_H +#define __LUNAIX_MEMPART_H /* Physical Adress Space Partition */ /* Generated from mempart.h.j2. Do NOT modify */ @@ -15,9 +17,9 @@ #define KERNEL_EXEC_SIZE 0x4000000UL #define KERNEL_EXEC_END 0xc3ffffffUL -#define PD_MOUNT 0xc4000000UL -#define PD_MOUNT_SIZE 0x400000UL -#define PD_MOUNT_END 0xc43fffffUL +#define VMS_MOUNT_1 0xc4000000UL +#define VMS_MOUNT_1_SIZE 0x400000UL +#define VMS_MOUNT_1_END 0xc43fffffUL #define PG_MOUNT_1 0xc4400000UL #define PG_MOUNT_1_SIZE 0x1000UL @@ -35,11 +37,12 @@ #define PG_MOUNT_4_SIZE 0x1000UL #define PG_MOUNT_4_END 0xc4403fffUL -#define VMAP 0xc4404000UL -#define VMAP_SIZE 0x3b7fc000UL +#define VMAP 0xc4800000UL +#define VMAP_SIZE 0x3b400000UL #define VMAP_END 0xffbfffffUL #define PD_REF 0xffc00000UL #define PD_REF_SIZE 0x400000UL #define PD_REF_END 0xffffffffUL +#endif \ No newline at end of file diff --git a/lunaix-os/arch/i386/includes/sys/pci_hba.h b/lunaix-os/arch/i386/includes/sys/pci_hba.h new file mode 100644 index 0000000..0546dca --- /dev/null +++ b/lunaix-os/arch/i386/includes/sys/pci_hba.h @@ -0,0 +1,37 @@ +#ifndef __LUNAIX_PCI_HBA_H +#define __LUNAIX_PCI_HBA_H + +#include +#include + +#include "port_io.h" + +#define PCI_CONFIG_ADDR 0xcf8 +#define PCI_CONFIG_DATA 0xcfc + +static inline pci_reg_t +pci_read_cspace(ptr_t base, int offset) +{ + port_wrdword(PCI_CONFIG_ADDR, base | (offset & ~0x3)); + return port_rddword(PCI_CONFIG_DATA); +} + +static inline void +pci_write_cspace(ptr_t base, int offset, pci_reg_t data) +{ + port_wrdword(PCI_CONFIG_ADDR, base | (offset & ~0x3)); + port_wrdword(PCI_CONFIG_DATA, data); +} + +/** + * @brief 配置并启用设备MSI支持。 + * 参阅:PCI LB Spec. (Rev 3) Section 6.8 & 6.8.1 + * 以及:Intel Manual, Vol 3, Section 10.11 + * + * @param device PCI device + * @param vector interrupt vector. + */ +void +pci_setup_msi(struct pci_device* device, int vector); + +#endif /* __LUNAIX_PCI_HBA_H */ diff --git a/lunaix-os/includes/hal/io.h b/lunaix-os/arch/i386/includes/sys/port_io.h similarity index 79% rename from lunaix-os/includes/hal/io.h rename to lunaix-os/arch/i386/includes/sys/port_io.h index a3768cf..da2798b 100644 --- a/lunaix-os/includes/hal/io.h +++ b/lunaix-os/arch/i386/includes/sys/port_io.h @@ -1,10 +1,10 @@ -#ifndef __LUNAIX_IO_H -#define __LUNAIX_IO_H +#ifndef __LUNAIX_PORT_IO_H +#define __LUNAIX_PORT_IO_H #include static inline u8_t -io_inb(int port) +port_rdbyte(int port) { u8_t data; asm volatile("inb %w1,%0" : "=a"(data) : "d"(port)); @@ -12,7 +12,7 @@ io_inb(int port) } static inline void -io_insb(int port, void* addr, int cnt) +port_rdbytes(int port, void* addr, int cnt) { asm volatile("cld\n" "repne\n" @@ -23,7 +23,7 @@ io_insb(int port, void* addr, int cnt) } static inline u16_t -io_inw(int port) +port_rdword(int port) { u16_t data; asm volatile("inw %w1,%0" : "=a"(data) : "d"(port)); @@ -31,7 +31,7 @@ io_inw(int port) } static inline void -io_insw(int port, void* addr, int cnt) +port_rdwords(int port, void* addr, int cnt) { asm volatile("cld\n" "repne\n" @@ -42,7 +42,7 @@ io_insw(int port, void* addr, int cnt) } static inline u32_t -io_inl(int port) +port_rddword(int port) { u32_t data; asm volatile("inl %w1,%0" : "=a"(data) : "d"(port)); @@ -50,7 +50,7 @@ io_inl(int port) } static inline void -io_insl(int port, void* addr, int cnt) +port_rddwords(int port, void* addr, int cnt) { asm volatile("cld\n" "repne\n" @@ -61,13 +61,13 @@ io_insl(int port, void* addr, int cnt) } static inline void -io_outb(int port, u8_t data) +port_wrbyte(int port, u8_t data) { asm volatile("outb %0, %w1" : : "a"(data), "d"(port)); } static inline void -io_outsb(int port, const void* addr, int cnt) +port_wrbytes(int port, const void* addr, int cnt) { asm volatile("cld\n" "repne\n" @@ -78,13 +78,13 @@ io_outsb(int port, const void* addr, int cnt) } static inline void -io_outw(int port, u16_t data) +port_wrword(int port, u16_t data) { asm volatile("outw %0,%w1" : : "a"(data), "d"(port)); } static inline void -io_outsw(int port, const void* addr, int cnt) +port_wrwords(int port, const void* addr, int cnt) { asm volatile("cld\n" "repne\n" @@ -95,7 +95,7 @@ io_outsw(int port, const void* addr, int cnt) } static inline void -io_outsl(int port, const void* addr, int cnt) +port_wrdwords(int port, const void* addr, int cnt) { asm volatile("cld\n" "repne\n" @@ -106,12 +106,13 @@ io_outsl(int port, const void* addr, int cnt) } static inline void -io_outl(int port, u32_t data) +port_wrdword(int port, u32_t data) { asm volatile("outl %0,%w1" : : "a"(data), "d"(port)); } + static inline void -io_delay(int counter) +port_delay(int counter) { asm volatile(" test %0, %0\n" " jz 1f\n" @@ -120,4 +121,4 @@ io_delay(int counter) "1: dec %0" ::"a"(counter)); } -#endif /* __LUNAIX_IO_H */ +#endif /* __LUNAIX_PORT_port_H */ diff --git a/lunaix-os/arch/i386/includes/sys/vectors.h b/lunaix-os/arch/i386/includes/sys/vectors.h index 7f27542..f352148 100644 --- a/lunaix-os/arch/i386/includes/sys/vectors.h +++ b/lunaix-os/arch/i386/includes/sys/vectors.h @@ -3,6 +3,8 @@ // clang-format off +#define TOTAL_IV 256 + #define FAULT_DIVISION_ERROR 0 #define INSTR_DEBUG 1 #define INT_NMI 2 @@ -26,19 +28,18 @@ #define FAULT_VIRTUALIZATION_EXCEPTION 20 #define FAULT_CONTROL_PROTECTION 21 +#define IV_BASE_END 31 + // LunaixOS related #define LUNAIX_SYS_PANIC 32 #define LUNAIX_SYS_CALL 33 -#define LUNAIX_SCHED 34 - -#define EX_INTERRUPT_BEGIN 200 -// Keyboard -#define PC_KBD_IV 201 -#define AHCI_HBA_IV 202 -#define UART_COM1 203 +// begin allocatable iv resources +#define IV_EX_BEGIN 50 +#define LUNAIX_SCHED 50 -#define RTC_TIMER_IV 210 +// end allocatable iv resources +#define IV_EX_END 249 // 来自APIC的中断有着最高的优先级。 // APIC related diff --git a/lunaix-os/arch/i386/mm/gdt.c b/lunaix-os/arch/i386/mm/gdt.c new file mode 100644 index 0000000..5d4ffe8 --- /dev/null +++ b/lunaix-os/arch/i386/mm/gdt.c @@ -0,0 +1,79 @@ +#include +#include + +#define SD_TYPE(x) (x << 8) +#define SD_CODE_DATA(x) (x << 12) +#define SD_DPL(x) (x << 13) +#define SD_PRESENT(x) (x << 15) +#define SD_AVL(x) (x << 20) +#define SD_64BITS(x) (x << 21) +#define SD_32BITS(x) (x << 22) +#define SD_4K_GRAN(x) (x << 23) + +#define SEG_LIM_L(x) (x & 0x0ffff) +#define SEG_LIM_H(x) (x & 0xf0000) +#define SEG_BASE_L(x) ((x & 0x0000ffff) << 16) +#define SEG_BASE_M(x) ((x & 0x00ff0000) >> 16) +#define SEG_BASE_H(x) (x & 0xff000000) + +#define SEG_DATA_RD 0x00 // Read-Only +#define SEG_DATA_RDA 0x01 // Read-Only, accessed +#define SEG_DATA_RDWR 0x02 // Read/Write +#define SEG_DATA_RDWRA 0x03 // Read/Write, accessed +#define SEG_DATA_RDEXPD 0x04 // Read-Only, expand-down +#define SEG_DATA_RDEXPDA 0x05 // Read-Only, expand-down, accessed +#define SEG_DATA_RDWREXPD 0x06 // Read/Write, expand-down +#define SEG_DATA_RDWREXPDA 0x07 // Read/Write, expand-down, accessed +#define SEG_CODE_EX 0x08 // Execute-Only +#define SEG_CODE_EXA 0x09 // Execute-Only, accessed +#define SEG_CODE_EXRD 0x0A // Execute/Read +#define SEG_CODE_EXRDA 0x0B // Execute/Read, accessed +#define SEG_CODE_EXC 0x0C // Execute-Only, conforming +#define SEG_CODE_EXCA 0x0D // Execute-Only, conforming, accessed +#define SEG_CODE_EXRDC 0x0E // Execute/Read, conforming +#define SEG_CODE_EXRDCA 0x0F // Execute/Read, conforming, accessed + +#define SEG_R0_CODE \ + SD_TYPE(SEG_CODE_EXRD) | SD_CODE_DATA(1) | SD_DPL(0) | SD_PRESENT(1) | \ + SD_AVL(0) | SD_64BITS(0) | SD_32BITS(1) | SD_4K_GRAN(1) + +#define SEG_R0_DATA \ + SD_TYPE(SEG_DATA_RDWR) | SD_CODE_DATA(1) | SD_DPL(0) | SD_PRESENT(1) | \ + SD_AVL(0) | SD_64BITS(0) | SD_32BITS(1) | SD_4K_GRAN(1) + +#define SEG_R3_CODE \ + SD_TYPE(SEG_CODE_EXRD) | SD_CODE_DATA(1) | SD_DPL(3) | SD_PRESENT(1) | \ + SD_AVL(0) | SD_64BITS(0) | SD_32BITS(1) | SD_4K_GRAN(1) + +#define SEG_R3_DATA \ + SD_TYPE(SEG_DATA_RDWR) | SD_CODE_DATA(1) | SD_DPL(3) | SD_PRESENT(1) | \ + SD_AVL(0) | SD_64BITS(0) | SD_32BITS(1) | SD_4K_GRAN(1) + +#define SEG_TSS SD_TYPE(9) | SD_DPL(0) | SD_PRESENT(1) + +#define GDT_ENTRY 6 + +u64_t _gdt[GDT_ENTRY]; +u16_t _gdt_limit = sizeof(_gdt) - 1; + +void +_set_gdt_entry(u32_t index, u32_t base, u32_t limit, u32_t flags) +{ + _gdt[index] = + SEG_BASE_H(base) | flags | SEG_LIM_H(limit) | SEG_BASE_M(base); + _gdt[index] <<= 32; + _gdt[index] |= SEG_BASE_L(base) | SEG_LIM_L(limit); +} + +extern struct x86_tss _tss; + +void +_init_gdt() +{ + _set_gdt_entry(0, 0, 0, 0); + _set_gdt_entry(1, 0, 0xfffff, SEG_R0_CODE); + _set_gdt_entry(2, 0, 0xfffff, SEG_R0_DATA); + _set_gdt_entry(3, 0, 0xfffff, SEG_R3_CODE); + _set_gdt_entry(4, 0, 0xfffff, SEG_R3_DATA); + _set_gdt_entry(5, (u32_t)&_tss, sizeof(struct x86_tss) - 1, SEG_TSS); +} \ No newline at end of file diff --git a/lunaix-os/arch/i386/pfault.c b/lunaix-os/arch/i386/mm/pfault.c similarity index 99% rename from lunaix-os/arch/i386/pfault.c rename to lunaix-os/arch/i386/mm/pfault.c index 58c7ec2..4c28a95 100644 --- a/lunaix-os/arch/i386/pfault.c +++ b/lunaix-os/arch/i386/mm/pfault.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -8,6 +7,7 @@ #include #include #include +#include #include diff --git a/lunaix-os/arch/i386/proc.c b/lunaix-os/arch/i386/proc.c index 67f3f73..565d258 100644 --- a/lunaix-os/arch/i386/proc.c +++ b/lunaix-os/arch/i386/proc.c @@ -1,5 +1,12 @@ #include +#include +#include + +volatile struct x86_tss _tss = { .link = 0, + .esp0 = KERNEL_STACK_END, + .ss0 = KDATA_SEG }; + void proc_init_transfer(struct proc_info* proc, ptr_t stack_top, diff --git a/lunaix-os/arch/i386/tss.c b/lunaix-os/arch/i386/tss.c deleted file mode 100644 index 22a996a..0000000 --- a/lunaix-os/arch/i386/tss.c +++ /dev/null @@ -1,7 +0,0 @@ -#include -#include -#include - -volatile struct x86_tss _tss = { .link = 0, - .esp0 = KSTACK_TOP, - .ss0 = KDATA_SEG }; \ No newline at end of file diff --git a/lunaix-os/hal/acpi/acpi.c b/lunaix-os/hal/acpi/acpi.c index 559befe..7ad3f06 100644 --- a/lunaix-os/hal/acpi/acpi.c +++ b/lunaix-os/hal/acpi/acpi.c @@ -16,12 +16,12 @@ int acpi_rsdp_validate(acpi_rsdp_t* rsdp); acpi_rsdp_t* -acpi_locate_rsdp(multiboot_info_t* mb_info); +acpi_locate_rsdp(); int -acpi_init(multiboot_info_t* mb_info) +acpi_init() { - acpi_rsdp_t* rsdp = acpi_locate_rsdp(mb_info); + acpi_rsdp_t* rsdp = acpi_locate_rsdp(); assert_msg(rsdp, "Fail to locate ACPI_RSDP"); assert_msg(acpi_rsdp_validate(rsdp), "Invalid ACPI_RSDP (checksum failed)"); @@ -82,7 +82,7 @@ acpi_rsdp_validate(acpi_rsdp_t* rsdp) } u8_t -acpi_gistranslate(u8_t old_irq) +acpi_gsimap(u8_t old_irq) { if (old_irq >= 24) { return old_irq; @@ -94,37 +94,10 @@ acpi_gistranslate(u8_t old_irq) #define VIRTUAL_BOX_PROBLEM acpi_rsdp_t* -acpi_locate_rsdp(multiboot_info_t* mb_info) +acpi_locate_rsdp() { acpi_rsdp_t* rsdp = NULL; - // You can't trust memory map from multiboot in virtual box! - // They put ACPI RSDP in the FUCKING 0xe0000 !!! - // Which is reported to be free area bt multiboot! - // SWEET CELESTIA!!! -#ifndef VIRTUAL_BOX_PROBLEM - multiboot_memory_map_t* mmap = (multiboot_memory_map_t*)mb_info->mmap_addr; - for (size_t i = 0, j = 0; j < mb_info->mmap_length && !rsdp; - i++, j += MB_MMAP_ENTRY_SIZE) { - multiboot_memory_map_t entry = mmap[i]; - if (entry.type != MULTIBOOT_MEMORY_RESERVED || - entry.addr_low > 0x100000) { - continue; - } - - u8_t* mem_start = entry.addr_low & ~0xf; - size_t len = entry.len_low; - for (size_t j = 0; j < len; j += 16) { - u32_t sig_low = *((u32_t*)(mem_start + j)); - // u32_t sig_high = *((u32_t*)(mem_start+j) + 1); - if (sig_low == ACPI_RSDP_SIG_L) { - rsdp = (acpi_rsdp_t*)(mem_start + j); - break; - } - } - } -#else - // You know what, I just search the entire 1MiB for Celestia's sake. ptr_t mem_start = 0x4000; for (; mem_start < 0x100000; mem_start += 16) { u32_t sig_low = *((u32_t*)mem_start); @@ -136,7 +109,6 @@ acpi_locate_rsdp(multiboot_info_t* mb_info) break; } } -#endif return rsdp; } \ No newline at end of file diff --git a/lunaix-os/hal/ahci/ahci.c b/lunaix-os/hal/ahci/ahci.c index 249b699..8059760 100644 --- a/lunaix-os/hal/ahci/ahci.c +++ b/lunaix-os/hal/ahci/ahci.c @@ -12,8 +12,11 @@ #include #include #include - #include + +#include +#include + #include #include #include @@ -33,7 +36,7 @@ LOG_MODULE("AHCI") -struct llist_header ahcis; +DEFINE_LLIST(ahcis); static char sata_ifs[][20] = { "Not detected", "SATA I (1.5Gbps)", @@ -73,17 +76,10 @@ __hba_reset_port(hba_reg_t* port_reg) } // 如果port未响应,则继续执行重置 port_reg[HBA_RPxSCTL] = (port_reg[HBA_RPxSCTL] & ~0xf) | 1; - io_delay(100000); // 等待至少一毫秒,差不多就行了 + port_delay(100000); // 等待至少一毫秒,差不多就行了 port_reg[HBA_RPxSCTL] &= ~0xf; } -void -ahci_init() -{ - llist_init_head(&ahcis); - pci_add_driver("Serial ATA AHCI", AHCI_HBA_CLASS, 0, 0, ahci_driver_init); -} - void* ahci_driver_init(struct pci_device* ahci_dev) { @@ -203,6 +199,7 @@ ahci_driver_init(struct pci_device* ahci_dev) return ahci_drv; } +EXPORT_PCI_DEVICE(pci_ahci, AHCI_HBA_CLASS, 0, 0, ahci_driver_init); void ahci_register_device(struct hba_device* hbadev) diff --git a/lunaix-os/hal/intc.c b/lunaix-os/hal/intc.c new file mode 100644 index 0000000..ae08909 --- /dev/null +++ b/lunaix-os/hal/intc.c @@ -0,0 +1,24 @@ +#include +#include + +#include + +struct intc_context arch_intc_ctx; + +void +intc_irq_attach(int irq, int iv, cpu_t dest, u32_t flags) +{ + arch_intc_ctx.irq_attach(&arch_intc_ctx, irq, iv, dest, flags); +} + +void +intc_notify_eoi(cpu_t id, int iv) +{ + arch_intc_ctx.notify_eoi(&arch_intc_ctx, id, iv); +} + +void +intc_notify_eos(cpu_t id) +{ + intc_notify_eoi(id, LUNAIX_SCHED); +} \ No newline at end of file diff --git a/lunaix-os/hal/ioapic.c b/lunaix-os/hal/ioapic.c deleted file mode 100644 index f0bd706..0000000 --- a/lunaix-os/hal/ioapic.c +++ /dev/null @@ -1,47 +0,0 @@ -#include -#include -#include -#include -#include - -#define IOAPIC_REG_SEL *((volatile u32_t*)(_ioapic_base + IOAPIC_IOREGSEL)) -#define IOAPIC_REG_WIN *((volatile u32_t*)(_ioapic_base + IOAPIC_IOWIN)) - -static volatile ptr_t _ioapic_base; - -void -ioapic_init() -{ - // Remapping the IRQs - - acpi_context* acpi_ctx = acpi_get_context(); - - _ioapic_base = - (ptr_t)ioremap(acpi_ctx->madt.ioapic->ioapic_addr & ~0xfff, 4096); -} - -void -ioapic_write(u8_t sel, u32_t val) -{ - IOAPIC_REG_SEL = sel; - IOAPIC_REG_WIN = val; -} - -u32_t -ioapic_read(u8_t sel) -{ - IOAPIC_REG_SEL = sel; - return IOAPIC_REG_WIN; -} - -void -ioapic_redirect(u8_t irq, u8_t vector, u8_t dest, u32_t flags) -{ - u8_t reg_sel = IOAPIC_IOREDTBL_BASE + irq * 2; - - // Write low 32 bits - ioapic_write(reg_sel, (vector | flags) & 0x1FFFF); - - // Write high 32 bits - ioapic_write(reg_sel + 1, (dest << 24)); -} \ No newline at end of file diff --git a/lunaix-os/hal/pci.c b/lunaix-os/hal/pci.c index 96cd676..1457aa1 100644 --- a/lunaix-os/hal/pci.c +++ b/lunaix-os/hal/pci.c @@ -8,9 +8,9 @@ * @copyright Copyright (c) 2022 * */ -#include -#include #include +#include + #include #include #include @@ -145,7 +145,7 @@ pci_probe_msi_info(struct pci_device* device) } } -void +static void __pci_read_cspace(struct twimap* map) { struct pci_device* pcidev = (struct pci_device*)(map->data); @@ -158,21 +158,21 @@ __pci_read_cspace(struct twimap* map) map->size_acc = 256; } -void +static void __pci_read_revid(struct twimap* map) { int class = twimap_data(map, struct pci_device*)->class_info; twimap_printf(map, "0x%x", PCI_DEV_REV(class)); } -void +static void __pci_read_class(struct twimap* map) { int class = twimap_data(map, struct pci_device*)->class_info; twimap_printf(map, "0x%x", PCI_DEV_CLASS(class)); } -void +static void __pci_bar_read(struct twimap* map) { struct pci_device* pcidev = twimap_data(map, struct pci_device*); @@ -200,7 +200,7 @@ __pci_bar_read(struct twimap* map) twimap_printf(map, "\n"); } -int +static int __pci_bar_gonext(struct twimap* map) { if (twimap_index(map, int) >= 5) { @@ -240,6 +240,7 @@ pci_build_fsmapping() map->go_next = __pci_bar_gonext; } } +EXPORT_TWIFS_PLUGIN(pci_devs, pci_build_fsmapping); size_t pci_bar_sizing(struct pci_device* dev, u32_t* bar_out, u32_t bar_num) @@ -261,36 +262,6 @@ pci_bar_sizing(struct pci_device* dev, u32_t* bar_out, u32_t bar_num) return ~sized + 1; } -void -pci_setup_msi(struct pci_device* device, int vector) -{ - // Dest: APIC#0, Physical Destination, No redirection - u32_t msi_addr = (__APIC_BASE_PADDR); - - // Edge trigger, Fixed delivery - u32_t msi_data = vector; - - pci_write_cspace( - device->cspace_base, PCI_MSI_ADDR(device->msi_loc), msi_addr); - - pci_reg_t reg1 = pci_read_cspace(device->cspace_base, device->msi_loc); - pci_reg_t msg_ctl = reg1 >> 16; - - int offset = !!(msg_ctl & MSI_CAP_64BIT) * 4; - pci_write_cspace(device->cspace_base, - PCI_MSI_DATA(device->msi_loc, offset), - msi_data & 0xffff); - - if ((msg_ctl & MSI_CAP_MASK)) { - pci_write_cspace( - device->cspace_base, PCI_MSI_MASK(device->msi_loc, offset), 0); - } - - // manipulate the MSI_CTRL to allow device using MSI to request service. - reg1 = (reg1 & 0xff8fffff) | 0x10000; - pci_write_cspace(device->cspace_base, device->msi_loc, reg1); -} - struct pci_device* pci_get_device_by_id(u16_t vendorId, u16_t deviceId) { @@ -363,16 +334,14 @@ pci_bind_driver(struct pci_device* pci_dev) } void -pci_init() +pci_load_devices() { - acpi_context* acpi = acpi_get_context(); - assert_msg(acpi, "ACPI not initialized."); - if (acpi->mcfg.alloc_num) { - // PCIe Enhanced Configuration Mechanism is supported. - // TODO: support PCIe addressing mechanism + int i = 0; + struct pci_driver* dev; + ldga_foreach(pci_dev_drivers, struct pci_driver*, i, dev) + { + llist_append(&pci_drivers, &dev->drivers); } - // Otherwise, fallback to use legacy PCI 3.0 method. - pci_probe(); - pci_build_fsmapping(); + pci_probe(); } \ No newline at end of file diff --git a/lunaix-os/hal/rtc.c b/lunaix-os/hal/rtc.c deleted file mode 100644 index bc2c2ef..0000000 --- a/lunaix-os/hal/rtc.c +++ /dev/null @@ -1,55 +0,0 @@ -/** - * @file rtc.c - * @author Lunaixsky - * @brief RTC & CMOS abstraction. Reference: MC146818A & Intel Series 500 PCH datasheet - * @version 0.1 - * @date 2022-03-07 - * - * @copyright Copyright (c) 2022 - * - */ -#include -#include - -void -rtc_init() { - u8_t regA = rtc_read_reg(RTC_REG_A | WITH_NMI_DISABLED); - regA = (regA & ~0x7f) | RTC_FREQUENCY_1024HZ | RTC_DIVIDER_33KHZ; - rtc_write_reg(RTC_REG_A | WITH_NMI_DISABLED, regA); - - // Make sure the rtc timer is disabled by default - rtc_disable_timer(); -} - -u8_t -rtc_read_reg(u8_t reg_selector) -{ - io_outb(RTC_INDEX_PORT, reg_selector); - return io_inb(RTC_TARGET_PORT); -} - -void -rtc_write_reg(u8_t reg_selector, u8_t val) -{ - io_outb(RTC_INDEX_PORT, reg_selector); - io_outb(RTC_TARGET_PORT, val); -} - -u8_t -bcd2dec(u8_t bcd) -{ - return ((bcd & 0xF0) >> 1) + ((bcd & 0xF0) >> 3) + (bcd & 0xf); -} - - -void -rtc_enable_timer() { - u8_t regB = rtc_read_reg(RTC_REG_B | WITH_NMI_DISABLED); - rtc_write_reg(RTC_REG_B | WITH_NMI_DISABLED, regB | RTC_TIMER_ON); -} - -void -rtc_disable_timer() { - u8_t regB = rtc_read_reg(RTC_REG_B | WITH_NMI_DISABLED); - rtc_write_reg(RTC_REG_B | WITH_NMI_DISABLED, regB & ~RTC_TIMER_ON); -} \ No newline at end of file diff --git a/lunaix-os/hal/rtc/hwrtc.c b/lunaix-os/hal/rtc/hwrtc.c new file mode 100644 index 0000000..8da6e22 --- /dev/null +++ b/lunaix-os/hal/rtc/hwrtc.c @@ -0,0 +1,17 @@ +#include + +const struct hwrtc* current_rtc; + +void +hwrtc_init() +{ + current_rtc = hwrtc_choose(); + + current_rtc->init(current_rtc); +} + +void +hwrtc_walltime(datetime_t* dt) +{ + current_rtc->get_walltime(current_rtc, dt); +} \ No newline at end of file diff --git a/lunaix-os/hal/rtc/mc146818a.c b/lunaix-os/hal/rtc/mc146818a.c new file mode 100644 index 0000000..98ea807 --- /dev/null +++ b/lunaix-os/hal/rtc/mc146818a.c @@ -0,0 +1,219 @@ +/** + * @file rtc.c + * @author Lunaixsky + * @brief RTC & CMOS abstraction. Reference: MC146818A & Intel Series 500 PCH + * datasheet + * @version 0.1 + * @date 2022-03-07 + * + * @copyright Copyright (c) 2022 + * + */ + +#include + +#include + +#include + +#include +#include + +#define RTC_INDEX_PORT 0x70 +#define RTC_TARGET_PORT 0x71 + +#define WITH_NMI_DISABLED 0x80 + +#define RTC_CURRENT_CENTRY 20 + +#define RTC_REG_YRS 0x9 +#define RTC_REG_MTH 0x8 +#define RTC_REG_DAY 0x7 +#define RTC_REG_WDY 0x6 +#define RTC_REG_HRS 0x4 +#define RTC_REG_MIN 0x2 +#define RTC_REG_SEC 0x0 + +#define RTC_REG_A 0xA +#define RTC_REG_B 0xB +#define RTC_REG_C 0xC +#define RTC_REG_D 0xD + +#define RTC_BIN_ENCODED(reg) (reg & 0x04) +#define RTC_24HRS_ENCODED(reg) (reg & 0x02) + +#define RTC_TIMER_BASE_FREQUENCY 1024 +#define RTC_TIMER_ON 0x40 + +#define RTC_FREQUENCY_1024HZ 0b110 +#define RTC_DIVIDER_33KHZ (0b010 << 4) + +struct mc146818 +{ + struct hwrtc* rtc_context; + u32_t rtc_iv; + int ticking; + void (*on_tick_cb)(const struct hwrtc*); +}; + +#define rtc_state(data) ((struct mc146818*)(data)) + +static u8_t +rtc_read_reg(u8_t reg_selector) +{ + port_wrbyte(RTC_INDEX_PORT, reg_selector); + return port_rdbyte(RTC_TARGET_PORT); +} + +static void +rtc_write_reg(u8_t reg_selector, u8_t val) +{ + port_wrbyte(RTC_INDEX_PORT, reg_selector); + port_wrbyte(RTC_TARGET_PORT, val); +} + +static u8_t +bcd2dec(u8_t bcd) +{ + return ((bcd & 0xF0) >> 1) + ((bcd & 0xF0) >> 3) + (bcd & 0xf); +} + +static void +rtc_enable_timer() +{ + u8_t regB = rtc_read_reg(RTC_REG_B | WITH_NMI_DISABLED); + rtc_write_reg(RTC_REG_B | WITH_NMI_DISABLED, regB | RTC_TIMER_ON); +} + +static void +rtc_disable_timer() +{ + u8_t regB = rtc_read_reg(RTC_REG_B | WITH_NMI_DISABLED); + rtc_write_reg(RTC_REG_B | WITH_NMI_DISABLED, regB & ~RTC_TIMER_ON); +} + +static void +clock_walltime(struct hwrtc* rtc, datetime_t* datetime) +{ + datetime_t current; + + do { + while (rtc_read_reg(RTC_REG_A) & 0x80) + ; + memcpy(¤t, datetime, sizeof(datetime_t)); + + datetime->year = rtc_read_reg(RTC_REG_YRS); + datetime->month = rtc_read_reg(RTC_REG_MTH); + datetime->day = rtc_read_reg(RTC_REG_DAY); + datetime->weekday = rtc_read_reg(RTC_REG_WDY); + datetime->hour = rtc_read_reg(RTC_REG_HRS); + datetime->minute = rtc_read_reg(RTC_REG_MIN); + datetime->second = rtc_read_reg(RTC_REG_SEC); + } while (!datatime_eq(datetime, ¤t)); + + u8_t regbv = rtc_read_reg(RTC_REG_B); + + // Convert from bcd to binary when needed + if (!RTC_BIN_ENCODED(regbv)) { + datetime->year = bcd2dec(datetime->year); + datetime->month = bcd2dec(datetime->month); + datetime->day = bcd2dec(datetime->day); + datetime->hour = bcd2dec(datetime->hour); + datetime->minute = bcd2dec(datetime->minute); + datetime->second = bcd2dec(datetime->second); + } + + // To 24 hour format + if (!RTC_24HRS_ENCODED(regbv) && (datetime->hour >> 7)) { + datetime->hour = 12 + (datetime->hour & 0x80); + } + + datetime->year += RTC_CURRENT_CENTRY * 100; +} + +static int +mc146818_check_support(struct hwrtc* rtc) +{ +#if __ARCH__ == i386 + return 1; +#else + return 0; +#endif +} + +static void +rtc_init(struct hwrtc* rtc) +{ + u8_t regA = rtc_read_reg(RTC_REG_A | WITH_NMI_DISABLED); + regA = (regA & ~0x7f) | RTC_FREQUENCY_1024HZ | RTC_DIVIDER_33KHZ; + rtc_write_reg(RTC_REG_A | WITH_NMI_DISABLED, regA); + + rtc_state(rtc->data)->rtc_context = rtc; + + // Make sure the rtc timer is disabled by default + rtc_disable_timer(); +} + +static struct mc146818 rtc_state = { .ticking = 0 }; + +static void +__rtc_tick(const isr_param* param) +{ + rtc_state.on_tick_cb(rtc_state.rtc_context); + + (void)rtc_read_reg(RTC_REG_C); +} + +static void +rtc_do_ticking(struct hwrtc* rtc, void (*on_tick)()) +{ + if (!on_tick || rtc_state(rtc->data)->ticking) { + return; + } + + struct mc146818* state = rtc_state(rtc->data); + state->ticking = 1; + state->on_tick_cb = on_tick; + + /* We realise that using rtc to tick something has an extremely rare use + * case (e.g., calibrating some timer). Therefore, we will release this + * allocated IV when rtc ticking is no longer required to save IV + * resources. + */ + state->rtc_iv = isrm_bindirq(PC_AT_IRQ_RTC, __rtc_tick); + + rtc_enable_timer(); +} + +static void +rtc_end_ticking(struct hwrtc* rtc) +{ + if (!rtc_state(rtc->data)->ticking) { + return; + } + + rtc_disable_timer(); + + // do some delay, ensure there is no more interrupt from rtc before we + // release isr + port_delay(1000); + + isrm_ivfree(rtc_state(rtc->data)->rtc_iv); + + rtc_state(rtc->data)->ticking = 0; +} + +static struct hwrtc hwrtc_mc146818a = { .name = "mc146818a", + .data = &rtc_state, + .init = rtc_init, + .base_freq = RTC_TIMER_BASE_FREQUENCY, + .supported = mc146818_check_support, + .get_walltime = clock_walltime, + .do_ticking = rtc_do_ticking, + .end_ticking = rtc_end_ticking }; + +struct hwrtc* +mc146818a_rtc_context() +{ + return &hwrtc_mc146818a; +} diff --git a/lunaix-os/hal/timer/apic_timer.c b/lunaix-os/hal/timer/apic_timer.c new file mode 100644 index 0000000..2d3dad5 --- /dev/null +++ b/lunaix-os/hal/timer/apic_timer.c @@ -0,0 +1,167 @@ +#include +#include +#include + +#include +#include +#include +#include + +#include + +LOG_MODULE("APIC_TIMER") + +#define LVT_ENTRY_TIMER(vector, mode) (LVT_DELIVERY_FIXED | mode | vector) +#define APIC_CALIBRATION_CONST 0x100000 + +// Don't optimize them! Took me an half hour to figure that out... + +static volatile u32_t rtc_counter = 0; +static volatile u8_t apic_timer_done = 0; +static volatile ticks_t base_freq = 0; +static volatile ticks_t systicks = 0; + +static timer_tick_cb tick_cb = NULL; + +static void +__rtc_on_tick_cb(struct hwrtc* param) +{ + rtc_counter++; +} + +static void +temp_intr_routine_apic_timer(const isr_param* param) +{ + base_freq = APIC_CALIBRATION_CONST / rtc_counter * current_rtc->base_freq; + apic_timer_done = 1; +} + +static void +apic_timer_tick_isr(const isr_param* param) +{ + systicks++; + + if (likely((ptr_t)tick_cb)) { + tick_cb(); + } +} + +static int +apic_timer_check(struct hwtimer_context* hwt) +{ + // TODO check whether apic timer is supported + return 1; +} + +static ticks_t +apic_get_systicks() +{ + return systicks; +} + +static ticks_t +apic_get_base_freq() +{ + return base_freq; +} + +void +apic_timer_init(struct hwtimer_context* timer, + u32_t hertz, + timer_tick_cb timer_cb) +{ + ticks_t frequency = hertz; + tick_cb = timer_cb; + + cpu_disable_interrupt(); + + // Setup APIC timer + + // Remap the IRQ 8 (rtc timer's vector) to RTC_TIMER_IV in ioapic + // (Remarks IRQ 8 is pin INTIN8) + // See IBM PC/AT Technical Reference 1-10 for old RTC IRQ + // See Intel's Multiprocessor Specification for IRQ - IOAPIC INTIN + // mapping config. + + // grab ourselves these irq numbers + u32_t iv_timer = isrm_ivexalloc(temp_intr_routine_apic_timer); + + // Setup a one-shot timer, we will use this to measure the bus speed. So we + // can then calibrate apic timer to work at *nearly* accurate hz + apic_write_reg(APIC_TIMER_LVT, + LVT_ENTRY_TIMER(iv_timer, LVT_TIMER_ONESHOT)); + + // Set divider to 64 + apic_write_reg(APIC_TIMER_DCR, APIC_TIMER_DIV64); + + /* + Timer calibration process - measure the APIC timer base frequency + + step 1: setup a temporary isr for RTC timer which trigger at each tick + (1024Hz) + step 2: setup a temporary isr for #APIC_TIMER_IV + step 3: setup the divider, APIC_TIMER_DCR + step 4: Startup RTC timer + step 5: Write a large value, v, to APIC_TIMER_ICR to start APIC timer + (this must be followed immediately after step 4) step 6: issue a write to + EOI and clean up. + + When the APIC ICR counting down to 0 #APIC_TIMER_IV triggered, save the + rtc timer's counter, k, and disable RTC timer immediately (although the + RTC interrupts should be blocked by local APIC as we are currently busy + on handling #APIC_TIMER_IV) + + So the apic timer frequency F_apic in Hz can be calculate as + v / F_apic = k / 1024 + => F_apic = v / k * 1024 + + */ + +#ifdef __LUNAIXOS_DEBUG__ + if (frequency < 1000) { + kprintf(KWARN "Frequency too low. Millisecond timer might be dodgy."); + } +#endif + + rtc_counter = 0; + apic_timer_done = 0; + + current_rtc->do_ticking(current_rtc, __rtc_on_tick_cb); + apic_write_reg(APIC_TIMER_ICR, APIC_CALIBRATION_CONST); // start APIC timer + + // enable interrupt, just for our RTC start ticking! + cpu_enable_interrupt(); + + wait_until(apic_timer_done); + + current_rtc->end_ticking(current_rtc); + + cpu_disable_interrupt(); + + assert_msg(base_freq, "Fail to initialize timer (NOFREQ)"); + + kprintf(KINFO "hw: %u Hz; os: %u Hz\n", base_freq, frequency); + + // cleanup + isrm_ivfree(iv_timer); + + apic_write_reg( + APIC_TIMER_LVT, + LVT_ENTRY_TIMER(isrm_ivexalloc(apic_timer_tick_isr), LVT_TIMER_PERIODIC)); + + timer->base_freq = base_freq; + + ticks_t tphz = base_freq / frequency; + apic_write_reg(APIC_TIMER_ICR, tphz); +} + +struct hwtimer_context* +apic_hwtimer_context() +{ + static struct hwtimer_context apic_hwt = { .name = "apic_timer", + .init = apic_timer_init, + .supported = apic_timer_check, + .systicks = apic_get_systicks }; + + return &apic_hwt; +} diff --git a/lunaix-os/hal/timer/hwtimer.c b/lunaix-os/hal/timer/hwtimer.c new file mode 100644 index 0000000..9c864c7 --- /dev/null +++ b/lunaix-os/hal/timer/hwtimer.c @@ -0,0 +1,40 @@ +#include +#include + +struct hwtimer_context* sys_hwtctx; + +void +hwtimer_init(u32_t hertz, void* tick_callback) +{ + struct hwtimer_context* hwt_ctx = hwtimer_choose(); + + hwt_ctx->init(hwt_ctx, hertz, tick_callback); + hwt_ctx->running_freq = hertz; + + sys_hwtctx = hwt_ctx; +} + +ticks_t +hwtimer_base_frequency() +{ + return sys_hwtctx->base_freq; +} + +ticks_t +hwtimer_current_systicks() +{ + return sys_hwtctx->systicks(); +} + +ticks_t +hwtimer_to_ticks(u32_t value, int unit) +{ + // in case system frequency is less than 1000Hz + if (unit != TIME_MS) { + return sys_hwtctx->running_freq * unit * value; + } + + ticks_t freq_ms = sys_hwtctx->running_freq / 1000; + + return freq_ms * value; +} \ No newline at end of file diff --git a/lunaix-os/includes/hal/acpi/acpi.h b/lunaix-os/includes/hal/acpi/acpi.h index 8f51a2c..de44d3a 100644 --- a/lunaix-os/includes/hal/acpi/acpi.h +++ b/lunaix-os/includes/hal/acpi/acpi.h @@ -1,7 +1,6 @@ #ifndef __LUNAIX_ACPI_ACPI_H #define __LUNAIX_ACPI_ACPI_H -#include #include #include @@ -16,8 +15,8 @@ #define ACPI_RSDP_SIG_L 0x20445352 // 'RSD ' #define ACPI_RSDP_SIG_H 0x20525450 // 'PTR ' -#define ACPI_MADT_SIG 0x43495041 // 'APIC' -#define ACPI_FADT_SIG 0x50434146 // 'FACP' Notice that it is not 'FADT'. +#define ACPI_MADT_SIG 0x43495041 // 'APIC' +#define ACPI_FADT_SIG 0x50434146 // 'FACP' Notice that it is not 'FADT'. // 'MCFG' (Not part of ACPI standard. See PCI Firmware Spec.) #define ACPI_MCFG_SIG 0x4746434d @@ -51,12 +50,12 @@ typedef struct } acpi_context; int -acpi_init(multiboot_info_t* mb_info); +acpi_init(); acpi_context* acpi_get_context(); u8_t -acpi_gistranslate(u8_t old_irq); +acpi_gsimap(u8_t old_irq); #endif /* __LUNAIX_ACPI_ACPI_H */ diff --git a/lunaix-os/includes/hal/ahci/ahci.h b/lunaix-os/includes/hal/ahci/ahci.h index fd22ffa..13312a5 100644 --- a/lunaix-os/includes/hal/ahci/ahci.h +++ b/lunaix-os/includes/hal/ahci/ahci.h @@ -21,13 +21,6 @@ struct ahci_driver int id; }; -/** - * @brief 初始化AHCI与HBA - * - */ -void -ahci_init(); - void ahci_parse_dev_info(struct hba_device* dev_info, u16_t* data); diff --git a/lunaix-os/includes/hal/apic_timer.h b/lunaix-os/includes/hal/apic_timer.h new file mode 100644 index 0000000..a076354 --- /dev/null +++ b/lunaix-os/includes/hal/apic_timer.h @@ -0,0 +1,8 @@ +#ifndef __LUNAIX_APIC_TIMER_H +#define __LUNAIX_APIC_TIMER_H + +#include + +struct hwtimer_context* apic_hwtimer_context(); + +#endif /* __LUNAIX_APIC_TIMER_H */ diff --git a/lunaix-os/includes/hal/hwrtc.h b/lunaix-os/includes/hal/hwrtc.h new file mode 100644 index 0000000..b43a2ff --- /dev/null +++ b/lunaix-os/includes/hal/hwrtc.h @@ -0,0 +1,33 @@ +#ifndef __LUNAIX_HWRTC_H +#define __LUNAIX_HWRTC_H + +#include + +struct hwrtc +{ + char* name; + void* data; + + ticks_t base_freq; + + int (*supported)(struct hwrtc*); + void (*init)(struct hwrtc*); + + void (*get_walltime)(struct hwrtc*, datetime_t*); + + void (*do_ticking)(struct hwrtc*, void (*on_tick)()); + void (*end_ticking)(struct hwrtc*); +}; + +extern const struct hwrtc* current_rtc; + +void +hwrtc_init(); + +struct hwrtc* +hwrtc_choose(); + +void +hwrtc_walltime(datetime_t* dt); + +#endif /* __LUNAIX_HWRTC_H */ diff --git a/lunaix-os/includes/hal/hwtimer.h b/lunaix-os/includes/hal/hwtimer.h new file mode 100644 index 0000000..efa72d8 --- /dev/null +++ b/lunaix-os/includes/hal/hwtimer.h @@ -0,0 +1,36 @@ +#ifndef __LUNAIX_HWTIMER_H +#define __LUNAIX_HWTIMER_H + +#include +#include + +typedef void (*timer_tick_cb)(); + +struct hwtimer_context +{ + char* name; + void* data; + + int (*supported)(struct hwtimer_context*); + void (*init)(struct hwtimer_context*, u32_t hertz, timer_tick_cb); + ticks_t (*systicks)(); + ticks_t base_freq; + ticks_t running_freq; +}; + +void +hwtimer_init(u32_t hertz, void* tick_callback); + +struct hwtimer_context* +hwtimer_choose(); + +ticks_t +hwtimer_base_frequency(); + +ticks_t +hwtimer_current_systicks(); + +ticks_t +hwtimer_to_ticks(u32_t value, int unit); + +#endif /* __LUNAIX_HWTIMER_H */ diff --git a/lunaix-os/includes/hal/intc.h b/lunaix-os/includes/hal/intc.h new file mode 100644 index 0000000..6a2828e --- /dev/null +++ b/lunaix-os/includes/hal/intc.h @@ -0,0 +1,53 @@ +#ifndef __LUNAIX_INTC_H +#define __LUNAIX_INTC_H + +#include + +#define IRQ_TRIG_EDGE 0b0 +#define IRQ_TRIG_LEVEL 0b1 + +#define IRQ_TYPE_FIXED (0b01 << 1) +#define IRQ_TYPE_NMI (0b11 << 1) +#define IRQ_TYPE (0b11 << 1) + +#define IRQ_VE_HI (0b1 << 3) +#define IRQ_VE_LO (0b0 << 3) + +#define IRQ_DEFAULT (IRQ_TRIG_EDGE | IRQ_TYPE_FIXED | IRQ_VE_HI) + +struct intc_context +{ + char* name; + void* data; + + void (*irq_attach)(struct intc_context*, + int irq, + int iv, + cpu_t dest, + u32_t flags); + void (*notify_eoi)(struct intc_context*, cpu_t id, int iv); +}; + +void +intc_init(); + +void +intc_irq_attach(int irq, int iv, cpu_t dest, u32_t flags); + +/** + * @brief Notify end of interrupt event + * + * @param id + */ +void +intc_notify_eoi(cpu_t id, int iv); + +/** + * @brief Notify end of scheduling event + * + * @param id + */ +void +intc_notify_eos(cpu_t id); + +#endif /* __LUNAIX_INTC_H */ diff --git a/lunaix-os/includes/hal/ioapic.h b/lunaix-os/includes/hal/ioapic.h deleted file mode 100644 index 4dccd7e..0000000 --- a/lunaix-os/includes/hal/ioapic.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef __LUNAIX_IOAPIC_H -#define __LUNAIX_IOAPIC_H - -#include - -#define IOAPIC_IOREGSEL 0x00 -#define IOAPIC_IOWIN 0x10 -#define IOAPIC_IOREDTBL_BASE 0x10 - -#define IOAPIC_REG_ID 0x00 -#define IOAPIC_REG_VER 0x01 -#define IOAPIC_REG_ARB 0x02 - -#define IOAPIC_DELMOD_FIXED 0b000 -#define IOAPIC_DELMOD_LPRIO 0b001 -#define IOAPIC_DELMOD_NMI 0b100 - -#define IOAPIC_MASKED (1 << 16) -#define IOAPIC_TRIG_LEVEL (1 << 15) -#define IOAPIC_INTPOL_L (1 << 13) -#define IOAPIC_DESTMOD_LOGIC (1 << 11) - -#define IOAPIC_BASE_VADDR 0x2000 - -void -ioapic_init(); - -void -ioapic_write(u8_t sel, u32_t val); - -u32_t -ioapic_read(u8_t sel); - -void -ioapic_redirect(u8_t irq, u8_t vector, u8_t dest, u32_t flags); - -#endif /* __LUNAIX_IOAPIC_H */ diff --git a/lunaix-os/includes/hal/pci.h b/lunaix-os/includes/hal/pci.h index b95f89a..2cc45b2 100644 --- a/lunaix-os/includes/hal/pci.h +++ b/lunaix-os/includes/hal/pci.h @@ -1,13 +1,10 @@ #ifndef __LUNAIX_PCI_H #define __LUNAIX_PCI_H -#include +#include #include #include -#define PCI_CONFIG_ADDR 0xcf8 -#define PCI_CONFIG_DATA 0xcfc - #define PCI_TDEV 0x0 #define PCI_TPCIBRIDGE 0x1 #define PCI_TCARDBRIDGE 0x2 @@ -61,6 +58,14 @@ typedef unsigned int pci_reg_t; #define BAR_TYPE_CACHABLE 0x2 #define PCI_DRV_NAME_LEN 32 +#define EXPORT_PCI_DEVICE(name_, class, vendor_id, dev_id, init_fn) \ + static struct pci_driver pcidev_##name_ = \ + (struct pci_driver){ .name = #name_, \ + .create_driver = (init_fn), \ + .dev_info = ((vendor_id) << 16) | (dev_id), \ + .dev_class = (class) }; \ + export_ldga_el(pci_dev_drivers, name_, ptr_t, &pcidev_##name_) + struct pci_driver; struct pci_base_addr @@ -97,30 +102,13 @@ struct pci_driver char name[PCI_DRV_NAME_LEN]; }; -// PCI Configuration Space (C-Space) r/w: -// Refer to "PCI Local Bus Specification, Rev.3, Section 3.2.2.3.2" - -static inline pci_reg_t -pci_read_cspace(u32_t base, int offset) -{ - io_outl(PCI_CONFIG_ADDR, base | (offset & ~0x3)); - return io_inl(PCI_CONFIG_DATA); -} - -static inline void -pci_write_cspace(u32_t base, int offset, pci_reg_t data) -{ - io_outl(PCI_CONFIG_ADDR, base | (offset & ~0x3)); - io_outl(PCI_CONFIG_DATA, data); -} - /** * @brief 初始化PCI。这主要是通过扫描PCI总线进行拓扑重建。注意,该 * 初始化不包括针对每个设备的初始化,因为那是设备驱动的事情。 * */ void -pci_init(); +pci_load_devices(); /** * @brief 根据类型代码(Class Code)去在拓扑中寻找一个设备 @@ -153,17 +141,6 @@ pci_get_device_by_id(u16_t vendorId, u16_t deviceId); size_t pci_bar_sizing(struct pci_device* dev, u32_t* bar_out, u32_t bar_num); -/** - * @brief 配置并启用设备MSI支持。 - * 参阅:PCI LB Spec. (Rev 3) Section 6.8 & 6.8.1 - * 以及:Intel Manual, Vol 3, Section 10.11 - * - * @param device PCI device - * @param vector interrupt vector. - */ -void -pci_setup_msi(struct pci_device* device, int vector); - void pci_add_driver(const char* name, u32_t class, diff --git a/lunaix-os/includes/hal/rtc.h b/lunaix-os/includes/hal/rtc.h deleted file mode 100644 index 46283d0..0000000 --- a/lunaix-os/includes/hal/rtc.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef __LUNAIX_RTC_H -#define __LUNAIX_RTC_H - -#include "io.h" - -#define RTC_INDEX_PORT 0x70 -#define RTC_TARGET_PORT 0x71 - -#define WITH_NMI_DISABLED 0x80 - -#define RTC_CURRENT_CENTRY 20 - -#define RTC_REG_YRS 0x9 -#define RTC_REG_MTH 0x8 -#define RTC_REG_DAY 0x7 -#define RTC_REG_WDY 0x6 -#define RTC_REG_HRS 0x4 -#define RTC_REG_MIN 0x2 -#define RTC_REG_SEC 0x0 - -#define RTC_REG_A 0xA -#define RTC_REG_B 0xB -#define RTC_REG_C 0xC -#define RTC_REG_D 0xD - -#define RTC_BIN_ENCODED(reg) (reg & 0x04) -#define RTC_24HRS_ENCODED(reg) (reg & 0x02) - -#define RTC_TIMER_BASE_FREQUENCY 1024 -#define RTC_TIMER_ON 0x40 - -#define RTC_FREQUENCY_1024HZ 0b110 -#define RTC_DIVIDER_33KHZ (0b010 << 4) - -void -rtc_init(); - -u8_t -rtc_read_reg(u8_t reg_selector); - -u8_t -bcd2dec(u8_t bcd); - -void -rtc_write_reg(u8_t reg_selector, u8_t val); - -void -rtc_enable_timer(); - -void -rtc_disable_timer(); - -#endif /* __LUNAIX_RTC_H */ diff --git a/lunaix-os/includes/hal/rtc/mc146818a.h b/lunaix-os/includes/hal/rtc/mc146818a.h new file mode 100644 index 0000000..3e81ff1 --- /dev/null +++ b/lunaix-os/includes/hal/rtc/mc146818a.h @@ -0,0 +1,13 @@ +#ifndef __LUNAIX_MC146818A_H +#define __LUNAIX_MC146818A_H + +/* + FIXME the drivers should go into ldga +*/ + +#include + +struct hwrtc* +mc146818a_rtc_context(); + +#endif /* __LUNAIX_MC146818A_H */ diff --git a/lunaix-os/includes/lunaix/boot_generic.h b/lunaix-os/includes/lunaix/boot_generic.h new file mode 100644 index 0000000..93e9e3d --- /dev/null +++ b/lunaix-os/includes/lunaix/boot_generic.h @@ -0,0 +1,71 @@ +#ifndef __LUNAIX_BOOT_GENERIC_H +#define __LUNAIX_BOOT_GENERIC_H + +#include + +// Free memory region +#define BOOT_MMAP_FREE 0 + +// Reserved memory region +#define BOOT_MMAP_RSVD 1 + +// Reclaimable memory region +#define BOOT_MMAP_RCLM 2 + +struct boot_mmapent +{ + ptr_t start; + size_t size; + int type; +}; + +struct boot_modent +{ + ptr_t start; + ptr_t end; + char* str; +}; + +struct boot_handoff +{ + size_t msize; + struct + { + size_t size; + struct boot_mmapent* mmap; + size_t mmap_len; + } mem; + + struct + { + ptr_t ksections; + size_t size; + + char** argv; + size_t argc; + } kexec; + + struct + { + size_t mods_num; + struct boot_modent* entries; + } mods; + + void (*release)(struct boot_handoff*); + void (*prepare)(struct boot_handoff*); + + // XXX: should arch specific boot detect platform interface provider? +}; + +#ifndef __BOOT_CODE__ +void +boot_begin(struct boot_handoff*); + +void +boot_end(struct boot_handoff*); + +void +boot_cleanup(); +#endif + +#endif /* __LUNAIX_BOOT_GENERIC_H */ diff --git a/lunaix-os/includes/lunaix/clock.h b/lunaix-os/includes/lunaix/clock.h index f3c67d9..6a3d26e 100644 --- a/lunaix-os/includes/lunaix/clock.h +++ b/lunaix-os/includes/lunaix/clock.h @@ -1,20 +1,7 @@ #ifndef __LUNAIX_CLOCK_H #define __LUNAIX_CLOCK_H -#include - -typedef u32_t time_t; - -typedef struct -{ - u32_t year; // use int32 as we need to store the 4-digit year - u8_t month; - u8_t day; - u8_t weekday; - u8_t hour; - u8_t minute; - u8_t second; -} datetime_t; +#include void clock_init(); @@ -22,9 +9,6 @@ clock_init(); void clock_walltime(datetime_t* datetime); -int -clock_datatime_eq(datetime_t* a, datetime_t* b); - /** * @brief 返回当前系统时间,即自从开机到当前时刻的毫秒时。 * @@ -36,19 +20,4 @@ clock_systime(); time_t clock_unixtime(); -static inline time_t -clock_tounixtime(datetime_t* dt) -{ - return (dt->year - 1970) * 31556926u + (dt->month - 1) * 2629743u + - (dt->day - 1) * 86400u + (dt->hour - 1) * 3600u + - (dt->minute - 1) * 60u + dt->second; -} - -static inline time_t -time_tounix(u32_t yyyy, u32_t mm, u32_t dd, u32_t hh, u32_t MM, u32_t ss) -{ - return (yyyy - 1970) * 31556926u + (mm - 1) * 2629743u + (dd - 1) * 86400u + - (hh - 1) * 3600u + (MM - 1) * 60u + ss; -} - #endif /* __LUNAIX_CLOCK_H */ diff --git a/lunaix-os/includes/lunaix/common.h b/lunaix-os/includes/lunaix/common.h index ac0b4d4..cb827fb 100644 --- a/lunaix-os/includes/lunaix/common.h +++ b/lunaix-os/includes/lunaix/common.h @@ -1,10 +1,6 @@ #ifndef __LUNAIX_CONSTANTS_H #define __LUNAIX_CONSTANTS_H -#define PG_SIZE_BITS 12 -#define PG_SIZE (1 << PG_SIZE_BITS) -#define PG_INDEX_BITS 10 - #define MEM_1MB 0x100000 #define MEM_4MB 0x400000 @@ -15,12 +11,6 @@ #define KSTACK_TOP ((USER_START - 1) & ~0xf) #define within_kstack(addr) (KSTACK_START <= (addr) && (addr) <= KSTACK_TOP) -#define KERNEL_MM_BASE 0xC0000000 - -#define KCODE_MAX_SIZE MEM_4MB -// #define KHEAP_START (KERNEL_MM_BASE + KCODE_MAX_SIZE) -// #define KHEAP_SIZE_MB 256 - #define VGA_FRAMEBUFFER 0xB8000 #define KCODE_SEG 0x08 diff --git a/lunaix-os/includes/lunaix/compiler.h b/lunaix-os/includes/lunaix/compiler.h index da376c1..a97c8c5 100644 --- a/lunaix-os/includes/lunaix/compiler.h +++ b/lunaix-os/includes/lunaix/compiler.h @@ -2,7 +2,8 @@ #define __LUNAIX_COMPILER_H #define likely(x) __builtin_expect((x), 1) +#define unlikely(x) __builtin_expect((x), 0) #define weak_alias(name) __attribute__((weak, alias(name))) - +#define noret __attribute__((noreturn)) #endif /* __LUNAIX_COMPILER_H */ diff --git a/lunaix-os/includes/lunaix/ds/ldga.h b/lunaix-os/includes/lunaix/ds/ldga.h new file mode 100644 index 0000000..c436798 --- /dev/null +++ b/lunaix-os/includes/lunaix/ds/ldga.h @@ -0,0 +1,27 @@ +/** + * @file ldga.h + * @author Lunaixsky (lunaxisky@qq.com) + * @brief Linker generated array definition + * @version 0.1 + * @date 2023-08-18 + * + * @copyright Copyright (c) 2023 + * + */ +#ifndef __LUNAIX_LDGA_H +#define __LUNAIX_LDGA_H + +#include + +#define export_ldga_el(ga_name, el_name, type, val) \ + type __attribute__((section(".lga." #ga_name))) \ + __lga_##ga_name##_##el_name = (type)(val) + +#define ldga_foreach(ga_name, el_type, index, el) \ + extern el_type __lga_##ga_name##_start[], __lga_##ga_name##_end; \ + for (index = 0, el = __lga_##ga_name##_start[index]; \ + (ptr_t)&__lga_##ga_name##_start[index] < \ + (ptr_t)&__lga_##ga_name##_end; \ + el = __lga_##ga_name##_start[++index]) + +#endif /* __LUNAIX_LDGA_H */ diff --git a/lunaix-os/includes/lunaix/fs/twifs.h b/lunaix-os/includes/lunaix/fs/twifs.h index 2ee5390..d77619e 100644 --- a/lunaix-os/includes/lunaix/fs/twifs.h +++ b/lunaix-os/includes/lunaix/fs/twifs.h @@ -1,6 +1,7 @@ #ifndef __LUNAIX_TWIFS_H #define __LUNAIX_TWIFS_H +#include #include #include #include @@ -34,6 +35,12 @@ struct twifs_node (type) twinode->data; \ }) +#define EXPORT_TWIFS_PLUGIN(label, plg_init) \ + export_ldga_el(twiplugin_inits, label, ptr_t, plg_init) + +void +twifs_register_plugins(); + void twifs_init(); diff --git a/lunaix-os/includes/lunaix/isrm.h b/lunaix-os/includes/lunaix/isrm.h index 5998dd1..6dd4a6f 100644 --- a/lunaix-os/includes/lunaix/isrm.h +++ b/lunaix-os/includes/lunaix/isrm.h @@ -11,34 +11,61 @@ #ifndef __LUNAIX_ISRM_H #define __LUNAIX_ISRM_H -#include #include - -#define IV_BASE 32 -#define IV_OS IV_BASE -#define IV_EX 48 -#define IV_MAX 256 +#include typedef void (*isr_cb)(const isr_param*); void isrm_init(); +/** + * @brief Release a iv resource + * + * @param iv + */ void isrm_ivfree(int iv); +/** + * @brief Allocate an iv resource for os services + * + * @param iv + */ int isrm_ivosalloc(isr_cb handler); +/** + * @brief Allocate an iv resource for external events + * + * @param iv + */ int isrm_ivexalloc(isr_cb handler); +/** + * @brief Bind a given irq and associated handler to an iv + * + * @param iv iv allocated by system + */ int isrm_bindirq(int irq, isr_cb irq_handler); +/** + * @brief Bind given iv with it's associated handler + * + * @param iv + * @param handler + */ void isrm_bindiv(int iv, isr_cb handler); +/** + * @brief Get the handler associated with the given iv + * + * @param iv + * @return isr_cb + */ isr_cb isrm_get(int iv); diff --git a/lunaix-os/includes/lunaix/mm/page.h b/lunaix-os/includes/lunaix/mm/page.h index 9afb2ed..38dcf71 100644 --- a/lunaix-os/includes/lunaix/mm/page.h +++ b/lunaix-os/includes/lunaix/mm/page.h @@ -3,18 +3,19 @@ #include #include +#define PG_SIZE_BITS 12 +#define PG_SIZE (1 << PG_SIZE_BITS) + #define PG_MAX_ENTRIES 1024U #define PG_LAST_TABLE PG_MAX_ENTRIES - 1 #define PG_FIRST_TABLE 0 #define PTE_NULL 0 -#define P2V(paddr) ((ptr_t)(paddr) + KERNEL_MM_BASE) -#define V2P(vaddr) ((ptr_t)(vaddr)-KERNEL_MM_BASE) - #define PG_ALIGN(addr) ((ptr_t)(addr)&0xFFFFF000UL) #define PG_MOD(addr) ((ptr_t)(addr) & ~PG_SIZE) #define PG_ALIGNED(addr) (!((ptr_t)(addr)&0x00000FFFUL)) +#define PN(addr) (((ptr_t)(addr) >> 12)) #define L1_INDEX(vaddr) (u32_t)(((ptr_t)(vaddr)&0xFFC00000UL) >> 22) #define L2_INDEX(vaddr) (u32_t)(((ptr_t)(vaddr)&0x003FF000UL) >> 12) @@ -96,25 +97,14 @@ typedef struct x86_pte_t entry[PG_MAX_ENTRIES]; } __attribute__((packed, aligned(4))) x86_page_table; -extern void __pg_mount_point; - /* 四个页挂载点,两个页目录挂载点: 用于临时创建&编辑页表 */ #define PG_MOUNT_RANGE(l1_index) (701 <= l1_index && l1_index <= 703) -#define VMS_MOUNT_1 (KERNEL_MM_BASE + KSIZE) -#define PG_MOUNT_BASE (VMS_MOUNT_1 + MEM_4MB) -#define PG_MOUNT_1 (PG_MOUNT_BASE) -#define PG_MOUNT_2 (PG_MOUNT_BASE + 0x1000) -#define PG_MOUNT_3 (PG_MOUNT_BASE + 0x2000) -#define PG_MOUNT_4 (PG_MOUNT_BASE + 0x3000) /* 当前进程内存空间挂载点 */ #define VMS_SELF L2_BASE_VADDR -#define CURPROC_PTE(vpn) \ - (&((x86_page_table*)(VMS_MOUNT_1 | (((vpn)&0xffc00) << 2))) \ - ->entry[(vpn)&0x3ff]) #define PTE_MOUNTED(mnt, vpn) \ (((x86_page_table*)((mnt) | (((vpn)&0xffc00) << 2)))->entry[(vpn)&0x3ff]) diff --git a/lunaix-os/includes/lunaix/mm/pmm.h b/lunaix-os/includes/lunaix/mm/pmm.h index 8141113..e0eab12 100644 --- a/lunaix-os/includes/lunaix/mm/pmm.h +++ b/lunaix-os/includes/lunaix/mm/pmm.h @@ -2,7 +2,7 @@ #define __LUNAIX_PMM_H // Physical memory manager -#include +#include #include #include diff --git a/lunaix-os/includes/lunaix/mm/vmm.h b/lunaix-os/includes/lunaix/mm/vmm.h index 5822faf..3f102db 100644 --- a/lunaix-os/includes/lunaix/mm/vmm.h +++ b/lunaix-os/includes/lunaix/mm/vmm.h @@ -7,11 +7,13 @@ // Virtual memory manager #define VMAP_NULL 0 + /** * @brief 映射模式:忽略已存在映射 * */ #define VMAP_IGNORE 1 + /** * @brief 映射模式:不作实际映射。该功能用于预留出特定的地址空间 * diff --git a/lunaix-os/includes/lunaix/peripheral/ps2kbd.h b/lunaix-os/includes/lunaix/peripheral/ps2kbd.h index 9a246ea..a6f2c63 100644 --- a/lunaix-os/includes/lunaix/peripheral/ps2kbd.h +++ b/lunaix-os/includes/lunaix/peripheral/ps2kbd.h @@ -1,7 +1,6 @@ #ifndef __LUNAIX_PS2KBD_H #define __LUNAIX_PS2KBD_H -#include #include #include diff --git a/lunaix-os/includes/lunaix/process.h b/lunaix-os/includes/lunaix/process.h index c3ac9a5..6ef1ff0 100644 --- a/lunaix-os/includes/lunaix/process.h +++ b/lunaix-os/includes/lunaix/process.h @@ -1,7 +1,6 @@ #ifndef __LUNAIX_PROCESS_H #define __LUNAIX_PROCESS_H -#include #include #include #include @@ -11,6 +10,7 @@ #include #include #include +#include // 虽然内核不是进程,但为了区分,这里使用Pid=-1来指代内核。这主要是方便物理页所有权检查。 #define KERNEL_PID -1 diff --git a/lunaix-os/includes/lunaix/spike.h b/lunaix-os/includes/lunaix/spike.h index e663a03..ae19357 100644 --- a/lunaix-os/includes/lunaix/spike.h +++ b/lunaix-os/includes/lunaix/spike.h @@ -1,6 +1,8 @@ #ifndef __LUNAIX_SPIKE_H #define __LUNAIX_SPIKE_H +#include + /** Some helper functions. As helpful as Spike the Dragon! :) **/ // 除法 v/(2^k) 向上取整 @@ -62,8 +64,6 @@ : 0) \ : (31 - __builtin_clz(x))) -#define __USER__ __attribute__((section(".usrtext"))) - #define DO_SPIN \ while (1) \ ; @@ -96,10 +96,10 @@ __assert_fail(const char* expr, const char* file, unsigned int line) #endif // __LUNAIXOS_NASSERT__ -void +void noret panick(const char* msg); -void +void noret panickf(const char* fmt, ...); #define wait_until(cond) \ diff --git a/lunaix-os/includes/lunaix/syscall.h b/lunaix-os/includes/lunaix/syscall.h index 3b0f070..1b9778f 100644 --- a/lunaix-os/includes/lunaix/syscall.h +++ b/lunaix-os/includes/lunaix/syscall.h @@ -1,16 +1,12 @@ #ifndef __LUNAIX_SYSCALL_H #define __LUNAIX_SYSCALL_H -#include #include #ifndef __ASM__ #define SYSCALL_ESTATUS(errno) -((errno) != 0) -void -syscall_install(); - #define asmlinkage __attribute__((regparm(0))) #define __PARAM_MAP1(t1, p1) t1 p1 @@ -40,9 +36,5 @@ syscall_install(); asmlinkage rettype __lxsys_##name( \ __PARAM_MAP5(t1, p1, t2, p2, t3, p3, t4, p4, t5, p5)) -#define __SYSCALL_INTERRUPTIBLE(code) \ - asm("sti"); \ - { code }; \ - asm("cli"); #endif #endif /* __LUNAIX_SYSCALL_H */ diff --git a/lunaix-os/includes/lunaix/time.h b/lunaix-os/includes/lunaix/time.h new file mode 100644 index 0000000..2b2c70a --- /dev/null +++ b/lunaix-os/includes/lunaix/time.h @@ -0,0 +1,48 @@ +#ifndef __LUNAIX_TIME_H +#define __LUNAIX_TIME_H + +#include + +#define TIME_MS -1000 +#define TIME_SEC 1 +#define TIME_MIN (TIME_SEC * 60) +#define TIME_HOUR (TIME_MIN * 60) + +typedef unsigned int ticks_t; +typedef u32_t time_t; + +typedef struct +{ + u32_t year; // use int32 as we need to store the 4-digit year + u8_t month; + u8_t day; + u8_t weekday; + u8_t hour; + u8_t minute; + u8_t second; +} datetime_t; + +static inline time_t +datetime_tounix(datetime_t* dt) +{ + return (dt->year - 1970) * 31556926u + (dt->month - 1) * 2629743u + + (dt->day - 1) * 86400u + (dt->hour - 1) * 3600u + + (dt->minute - 1) * 60u + dt->second; +} + +static inline time_t +time_tounix(u32_t yyyy, u32_t mm, u32_t dd, u32_t hh, u32_t MM, u32_t ss) +{ + return (yyyy - 1970) * 31556926u + (mm - 1) * 2629743u + (dd - 1) * 86400u + + (hh - 1) * 3600u + (MM - 1) * 60u + ss; +} + +static inline int +datatime_eq(datetime_t* a, datetime_t* b) +{ + return a->year == b->year && a->month == b->month && a->day == b->day && + a->weekday == b->weekday && a->minute == b->minute && + a->second == b->second; +} + +#endif /* __LUNAIX_TIME_H */ diff --git a/lunaix-os/includes/lunaix/timer.h b/lunaix-os/includes/lunaix/timer.h index 5ab3864..d1b7845 100644 --- a/lunaix-os/includes/lunaix/timer.h +++ b/lunaix-os/includes/lunaix/timer.h @@ -2,19 +2,18 @@ #define __LUNAIX_TIMER_H #include -#include +#include +#include #define SYS_TIMER_FREQUENCY_HZ 1024 #define TIMER_MODE_PERIODIC 0x1 -typedef u32_t ticks_t; - struct lx_timer_context { struct lx_timer* active_timers; /** - * @brief APIC timer base frequency (ticks per seconds) + * @brief timer hardware base frequency (ticks per seconds) * */ ticks_t base_frequency; @@ -22,7 +21,7 @@ struct lx_timer_context * @brief Desired system running frequency * */ - u32_t running_frequency; + ticks_t running_frequency; /** * @brief Ticks per hertz * @@ -30,6 +29,12 @@ struct lx_timer_context ticks_t tphz; }; +struct timer_init_param +{ + struct lx_timer_context* context; + void* timer_update_isr; +}; + struct lx_timer { struct llist_header link; @@ -46,7 +51,7 @@ struct lx_timer * @param frequency The frequency that timer should run in Hz. */ void -timer_init(u32_t frequency); +timer_init(); struct lx_timer* timer_run_second(u32_t second, diff --git a/lunaix-os/includes/lunaix/trace.h b/lunaix-os/includes/lunaix/trace.h new file mode 100644 index 0000000..80cf5f3 --- /dev/null +++ b/lunaix-os/includes/lunaix/trace.h @@ -0,0 +1,33 @@ +#ifndef __LUNAIX_TRACE_H +#define __LUNAIX_TRACE_H + +#include + +struct ksym_entry +{ + ptr_t pc; + u32_t label_off; +}; + +struct ksyms +{ + u32_t ksym_count; + u32_t ksym_label_off; + struct ksym_entry syms[0]; +}; + +struct trace_context +{ + struct ksyms* ksym_table; +}; + +void +trace_modksyms_init(struct boot_handoff* bhctx); + +struct ksym_entry* +trace_sym_lookup(ptr_t pc); + +void +trace_walkback(ptr_t fp); + +#endif /* __LUNAIX_TRACE_H */ diff --git a/lunaix-os/includes/lunaix/types.h b/lunaix-os/includes/lunaix/types.h index 1d6556b..8b0c0d6 100644 --- a/lunaix-os/includes/lunaix/types.h +++ b/lunaix-os/includes/lunaix/types.h @@ -23,6 +23,8 @@ typedef int pid_t; typedef unsigned long size_t; typedef unsigned long off_t; +typedef unsigned int cpu_t; + typedef u64_t lba_t; #endif /* __LUNAIX_TYPES_H */ diff --git a/lunaix-os/kernel.mk b/lunaix-os/kernel.mk index 1c07c90..c844703 100644 --- a/lunaix-os/kernel.mk +++ b/lunaix-os/kernel.mk @@ -4,7 +4,6 @@ include toolchain.mkinc define ksrc_dirs kernel hal - debug libs arch/$(ARCH) endef @@ -39,7 +38,11 @@ $(kbin): $(ksrc_objs) $(kbin_dir) $(call status_,LD,$@) @$(CC) -T link/linker.ld -o $(kbin) $(ksrc_objs) $(LDFLAGS) -all: $(kbin) +$(kbin_dir)/modksyms: $(kbin) + $(call status_,GEN,$@) + @$(PY) scripts/syms_export.py --bits=32 --order=little -o "$@" "$<" + +all: $(kbin) $(kbin_dir)/modksyms clean: @rm -f $(ksrc_objs) \ No newline at end of file diff --git a/lunaix-os/kernel/block/block.c b/lunaix-os/kernel/block/block.c index f699169..c4e29e1 100644 --- a/lunaix-os/kernel/block/block.c +++ b/lunaix-os/kernel/block/block.c @@ -1,16 +1,18 @@ -#include #include #include + +#include + #include + +#include #include #include #include +#include #include -#include - -#include - #include +#include #define BLOCK_EREAD 1 #define BLOCK_ESIG 2 diff --git a/lunaix-os/kernel/boot_helper.c b/lunaix-os/kernel/boot_helper.c new file mode 100644 index 0000000..fa87bff --- /dev/null +++ b/lunaix-os/kernel/boot_helper.c @@ -0,0 +1,82 @@ +#include +#include +#include +#include +#include +#include +#include + +/** + * @brief Reserve memory for kernel bootstrapping initialization + * + * @param bhctx + */ +void +boot_begin(struct boot_handoff* bhctx) +{ + bhctx->prepare(bhctx); + + struct boot_mmapent *mmap = bhctx->mem.mmap, *mmapent; + for (size_t i = 0; i < bhctx->mem.mmap_len; i++) { + mmapent = &mmap[i]; + size_t size_pg = PN(ROUNDUP(mmapent->size, PG_SIZE)); + + if (mmapent->type == BOOT_MMAP_FREE) { + pmm_mark_chunk_free(PN(mmapent->start), size_pg); + continue; + } + + ptr_t pa = PG_ALIGN(mmapent->start); + for (size_t j = 0; j < size_pg && pa < KERNEL_EXEC; + j++, pa += PM_PAGE_SIZE) { + vmm_set_mapping(VMS_SELF, pa, pa, PG_PREM_RW, VMAP_IGNORE); + } + } +} + +extern u8_t __kexec_boot_end; /* link/linker.ld */ + +/** + * @brief Release memory for kernel bootstrapping initialization + * + * @param bhctx + */ +void +boot_end(struct boot_handoff* bhctx) +{ + struct boot_mmapent *mmap = bhctx->mem.mmap, *mmapent; + for (size_t i = 0; i < bhctx->mem.mmap_len; i++) { + mmapent = &mmap[i]; + size_t size_pg = PN(ROUNDUP(mmapent->size, PG_SIZE)); + + if (mmapent->start >= KERNEL_EXEC || mmapent->type == BOOT_MMAP_FREE) { + continue; + } + + if (mmapent->type == BOOT_MMAP_RCLM) { + pmm_mark_chunk_free(PN(mmapent->start), size_pg); + } + + ptr_t pa = PG_ALIGN(mmapent->start); + for (size_t j = 0; j < size_pg && pa < KERNEL_EXEC; + j++, pa += PM_PAGE_SIZE) { + vmm_del_mapping(VMS_SELF, pa); + } + } + + bhctx->release(bhctx); +} + +/** + * @brief Clean up the boot stage code and data + * + */ +void +boot_cleanup() +{ + // clean up + for (size_t i = 0; i < (ptr_t)(&__kexec_boot_end); i += PG_SIZE) { + vmm_del_mapping(VMS_SELF, (ptr_t)i); + pmm_free_page(KERNEL_PID, (ptr_t)i); + } +} \ No newline at end of file diff --git a/lunaix-os/kernel/debug/gdbstub.c b/lunaix-os/kernel/debug/gdbstub.c index 38d35ad..072b6a4 100644 --- a/lunaix-os/kernel/debug/gdbstub.c +++ b/lunaix-os/kernel/debug/gdbstub.c @@ -32,10 +32,10 @@ * SOFTWARE. */ -#include #include #include #include +#include /***************************************************************************** * Types @@ -1191,8 +1191,8 @@ struct gdb_idt_gate /***************************************************************************** * Prototypes ****************************************************************************/ -#define gdb_x86_io_write_8(port, val) io_outb(port, val) -#define gdb_x86_io_read_8(port) io_inb(port) +#define gdb_x86_io_write_8(port, val) port_wrbyte(port, val) +#define gdb_x86_io_read_8(port) port_rdbyte(port) #define gdb_x86_serial_getc() serial_rx_byte(COM_PORT) #define gdb_x86_serial_putchar(ch) serial_tx_byte(COM_PORT, ch) diff --git a/lunaix-os/kernel/debug/sdbg.c b/lunaix-os/kernel/debug/sdbg.c index 60a89f3..42dc6c7 100644 --- a/lunaix-os/kernel/debug/sdbg.c +++ b/lunaix-os/kernel/debug/sdbg.c @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include diff --git a/lunaix-os/kernel/debug/trace.c b/lunaix-os/kernel/debug/trace.c new file mode 100644 index 0000000..c08a6f7 --- /dev/null +++ b/lunaix-os/kernel/debug/trace.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include + +#include + +static struct trace_context trace_ctx; + +void +trace_modksyms_init(struct boot_handoff* bhctx) +{ + struct boot_modent* modents = bhctx->mods.entries; + for (size_t i = 0; i < bhctx->mods.mods_num; i++) { + struct boot_modent* mod = &bhctx->mods.entries[i]; + if (streq(mod->str, "modksyms")) { + // In case boot loader does not place our ksyms on page boundary + ptr_t start = PG_ALIGN(mod->start); + ptr_t end = ROUNDUP(mod->end, PG_SIZE); + ptr_t ksym_va = (ptr_t)ioremap(start, (end - start)); + + trace_ctx.ksym_table = + (struct ksyms*)(ksym_va + (mod->start - start)); + } + } +} + +struct ksym_entry* +trace_sym_lookup(ptr_t pc) +{ + return NULL; +} + +void +trace_walkback(ptr_t fp) +{ +} \ No newline at end of file diff --git a/lunaix-os/kernel/device/builtin/devnull.c b/lunaix-os/kernel/device/builtin/devnull.c index 977c385..6f0b4a0 100644 --- a/lunaix-os/kernel/device/builtin/devnull.c +++ b/lunaix-os/kernel/device/builtin/devnull.c @@ -1,4 +1,5 @@ #include +#include int __null_wr_pg(struct device* dev, void* buf, size_t offset) diff --git a/lunaix-os/kernel/device/builtin/devrand.c b/lunaix-os/kernel/device/builtin/devrand.c index ce85c39..bce0f3a 100644 --- a/lunaix-os/kernel/device/builtin/devrand.c +++ b/lunaix-os/kernel/device/builtin/devrand.c @@ -1,5 +1,6 @@ #include #include +#include #include LOG_MODULE("rand") diff --git a/lunaix-os/kernel/device/input.c b/lunaix-os/kernel/device/input.c index a96cb00..bf4c157 100644 --- a/lunaix-os/kernel/device/input.c +++ b/lunaix-os/kernel/device/input.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include diff --git a/lunaix-os/kernel/fs/fs_export.c b/lunaix-os/kernel/fs/fs_export.c index 046204f..bdc02d4 100644 --- a/lunaix-os/kernel/fs/fs_export.c +++ b/lunaix-os/kernel/fs/fs_export.c @@ -59,4 +59,5 @@ vfs_export_attributes() map = twifs_mapping(NULL, NULL, "version"); map->read = __version_rd; -} \ No newline at end of file +} +EXPORT_TWIFS_PLUGIN(vfs_general, vfs_export_attributes); \ No newline at end of file diff --git a/lunaix-os/kernel/fs/twifs/twifs.c b/lunaix-os/kernel/fs/twifs/twifs.c index 5cf47ee..729b5f7 100644 --- a/lunaix-os/kernel/fs/twifs/twifs.c +++ b/lunaix-os/kernel/fs/twifs/twifs.c @@ -242,6 +242,17 @@ twifs_init() fs_root = twifs_dir_node(NULL, NULL, 0, 0); } +void +twifs_register_plugins() +{ + int i = 0; + ptr_t init_twifs_plugin_fn; + ldga_foreach(twiplugin_inits, ptr_t, i, init_twifs_plugin_fn) + { + ((void (*)())init_twifs_plugin_fn)(); + } +} + int __twifs_twimap_file_read(struct v_inode* inode, void* buf, diff --git a/lunaix-os/kernel/kinit.c b/lunaix-os/kernel/kinit.c index 6cb5871..607ba20 100644 --- a/lunaix-os/kernel/kinit.c +++ b/lunaix-os/kernel/kinit.c @@ -1,8 +1,10 @@ +#include +#include #include #include #include +#include #include -#include #include #include #include @@ -13,28 +15,21 @@ #include #include #include -#include +#include #include #include +#include +#include +#include + #include -#include #include +#include #include #include -extern u8_t __kernel_start; -extern u8_t __kernel_end; -extern u8_t __init_hhk_end; - -#define PP_KERN_SHARED (PP_FGSHARED | PP_TKERN) - -// Set remotely by kernel/asm/x86/prologue.S -multiboot_info_t* _k_init_mb_info; - -x86_page_table* __kernel_ptd; - extern void __proc0(); /* proc0.c */ @@ -42,52 +37,54 @@ void spawn_proc0(); void -setup_memory(multiboot_memory_map_t* map, size_t map_size); +kmem_init(struct boot_handoff* bhctx); void -_kernel_pre_init() +kernel_bootstrap(struct boot_handoff* bhctx) { - // interrupts - exception_init(); - - // memory - pmm_init(MEM_1MB + (_k_init_mb_info->mem_upper << 10)); + pmm_init(bhctx->mem.size); vmm_init(); - unsigned int map_size = - _k_init_mb_info->mmap_length / sizeof(multiboot_memory_map_t); - - setup_memory((multiboot_memory_map_t*)_k_init_mb_info->mmap_addr, map_size); -} - -void -_kernel_init() -{ - int errno = 0; + /* Begin kernel bootstrapping sequence */ + boot_begin(bhctx); - // allocators - cake_init(); - valloc_init(); + /* Setup kernel memory layout and services */ + kmem_init(bhctx); - sched_init(); + /* Prepare stack trace environment */ + trace_modksyms_init(bhctx); // crt tty_init(ioremap(VGA_FRAMEBUFFER, PG_SIZE)); tty_set_theme(VGA_COLOR_WHITE, VGA_COLOR_BLACK); + lxconsole_init(); + + /* Get platform configuration */ + acpi_init(); - // file system & device subsys + /* Let's get fs online as soon as possible, as things rely on them */ vfs_init(); fsm_init(); input_init(); - vfs_export_attributes(); + /* Get intc online, this is the cornerstone when initing devices */ + intc_init(); - lxconsole_init(); + /* System timing and clock support */ + clock_init(); + timer_init(); + + block_init(); + /* the bare metal are now happy, let's get software over with */ + sched_init(); + + int errno = 0; if ((errno = vfs_mount_root("ramfs", NULL))) { panickf("Fail to mount root. (errno=%d)", errno); } + /* Mount these system-wide pseudo-fs */ vfs_mount("/dev", "devfs", NULL, 0); vfs_mount("/sys", "twifs", NULL, MNT_RO); vfs_mount("/task", "taskfs", NULL, MNT_RO); @@ -95,7 +92,10 @@ _kernel_init() lxconsole_spawn_ttydev(); device_init_builtin(); - syscall_install(); + /* Finish up bootstrapping sequence, we are ready to spawn the root process + * and start geting into uspace + */ + boot_end(bhctx); spawn_proc0(); } @@ -154,35 +154,26 @@ spawn_proc0() // 由于时钟中断与APIC未就绪,我们需要手动进行第一次调度。这里也会同时隐式地恢复我们的eflags.IF位 proc0->state = PS_RUNNING; - asm volatile("pushl %0\n" - "jmp switch_to\n" ::"r"(proc0)); + switch_context(proc0); /* Should not return */ assert_msg(0, "Unexpected Return"); } -// 按照 Memory map 标识可用的物理页 void -setup_memory(multiboot_memory_map_t* map, size_t map_size) +kmem_init(struct boot_handoff* bhctx) { - - // First pass, to mark the physical pages - for (unsigned int i = 0; i < map_size; i++) { - multiboot_memory_map_t mmap = map[i]; - if (mmap.type == MULTIBOOT_MEMORY_AVAILABLE) { - // 整数向上取整除法 - ptr_t pg = map[i].addr_low + 0x0fffU; - pmm_mark_chunk_free(pg >> PG_SIZE_BITS, - map[i].len_low >> PG_SIZE_BITS); - } - } - + extern u8_t __kexec_end; // 将内核占据的页,包括前1MB,hhk_init 设为已占用 - size_t pg_count = V2P(&__kernel_end) >> PG_SIZE_BITS; + size_t pg_count = ((ptr_t)&__kexec_end - KERNEL_EXEC) >> PG_SIZE_BITS; pmm_mark_chunk_occupied(KERNEL_PID, 0, pg_count, PP_FGLOCKED); // reserve higher half - for (size_t i = L1_INDEX(KERNEL_MM_BASE); i < 1023; i++) { + for (size_t i = L1_INDEX(KERNEL_EXEC); i < 1023; i++) { assert(vmm_set_mapping(VMS_SELF, i << 22, 0, 0, VMAP_NOMAP)); } + + // allocators + cake_init(); + valloc_init(); } diff --git a/lunaix-os/kernel/mm/cake_export.c b/lunaix-os/kernel/mm/cake_export.c index 276e823..956423b 100644 --- a/lunaix-os/kernel/mm/cake_export.c +++ b/lunaix-os/kernel/mm/cake_export.c @@ -105,4 +105,5 @@ cake_export() { cake_export_pile(cake_root, pos); } -} \ No newline at end of file +} +EXPORT_TWIFS_PLUGIN(cake_alloc, cake_export); \ No newline at end of file diff --git a/lunaix-os/kernel/mm/cow.c b/lunaix-os/kernel/mm/cow.c index 6b46e48..a12d6e9 100644 --- a/lunaix-os/kernel/mm/cow.c +++ b/lunaix-os/kernel/mm/cow.c @@ -1,6 +1,8 @@ #include #include +#include + ptr_t vmm_dup_page(pid_t pid, ptr_t pa) { diff --git a/lunaix-os/kernel/mm/mmap.c b/lunaix-os/kernel/mm/mmap.c index 77e1264..fcdd91c 100644 --- a/lunaix-os/kernel/mm/mmap.c +++ b/lunaix-os/kernel/mm/mmap.c @@ -7,8 +7,10 @@ #include #include +#include + // any size beyond this is bullshit -#define BS_SIZE (KERNEL_MM_BASE - UMMAP_START) +#define BS_SIZE (KERNEL_EXEC - UMMAP_START) int mem_has_overlap(vm_regions_t* regions, ptr_t start, ptr_t end) @@ -101,7 +103,7 @@ mem_map(void** addr_out, return ENOMEM; found: - if (found_loc >= KERNEL_MM_BASE || found_loc < USER_START) { + if (found_loc >= KERNEL_EXEC || found_loc < USER_START) { return ENOMEM; } diff --git a/lunaix-os/kernel/mm/pmm.c b/lunaix-os/kernel/mm/pmm.c index 7589261..ffb51e6 100644 --- a/lunaix-os/kernel/mm/pmm.c +++ b/lunaix-os/kernel/mm/pmm.c @@ -108,9 +108,6 @@ pmm_alloc_page(pid_t owner, pp_attr_t attr) } } } - if (!good_page_found) { - __current->k_status = LXOUTOFMEM; - } return good_page_found; } diff --git a/lunaix-os/kernel/mm/vmap.c b/lunaix-os/kernel/mm/vmap.c index ad1a832..35f61e4 100644 --- a/lunaix-os/kernel/mm/vmap.c +++ b/lunaix-os/kernel/mm/vmap.c @@ -2,10 +2,9 @@ #include #include -#define VMAP_START PG_MOUNT_BASE + MEM_4MB -#define VMAP_END VMS_SELF +#include -static ptr_t start = VMAP_START; +static ptr_t start = VMAP; void* vmm_vmap(ptr_t paddr, size_t size, pt_attr attr) @@ -47,7 +46,7 @@ vmm_vmap(ptr_t paddr, size_t size, pt_attr attr) if (current_addr >= VMAP_END) { wrapped = 1; examed_size = 0; - current_addr = VMAP_START; + current_addr = VMAP; } } diff --git a/lunaix-os/kernel/peripheral/ps2kbd.c b/lunaix-os/kernel/peripheral/ps2kbd.c index 1547283..fc55ece 100644 --- a/lunaix-os/kernel/peripheral/ps2kbd.c +++ b/lunaix-os/kernel/peripheral/ps2kbd.c @@ -1,5 +1,3 @@ -#include -#include #include #include #include @@ -8,11 +6,13 @@ #include #include -#include #include +#include + #include -#include +#include +#include #define PS2_DEV_CMD_MAX_ATTEMPTS 5 @@ -123,30 +123,37 @@ ps2_kbd_init() kbd_idev = input_add_device("i8042-kbd"); - acpi_context* acpi_ctx = acpi_get_context(); - if (acpi_ctx->fadt.header.rev > 1) { - /* - * 只有当前ACPI版本大于1时,我们才使用FADT的IAPC_BOOT_ARCH去判断8042是否存在。 - * 这是一个坑,在ACPI v1中,这个字段是reserved!而这及至ACPI v2才出现。 - * 需要注意:Bochs 和 QEMU 使用的是ACPI v1,而非 v2 - * (virtualbox好像是v4) - * - * (2022/6/29) - * QEMU在7.0.0版本中,修复了FADT::IAPC_BOOT无法正确提供关于i8042的信息的bug - * https://wiki.qemu.org/ChangeLog/7.0#ACPI_.2F_SMBIOS - * - * 请看Bochs的bios源码(QEMU的BIOS其实是照抄bochs的,所以也是一个德行。。): - * https://bochs.sourceforge.io/cgi-bin/lxr/source/bios/rombios32.c#L1314 - */ - if (!(acpi_ctx->fadt.boot_arch & IAPC_ARCH_8042)) { - kprintf(KERROR "not found\n"); - // FUTURE: Some alternative fallback on this? Check PCI bus for USB - // controller instead? - return; - } - } else { - kprintf(KWARN "outdated FADT used, assuming exists.\n"); - } + /* FIXME This require systematical rework! */ + // acpi_context* acpi_ctx = acpi_get_context(); + // if (acpi_ctx->fadt.header.rev > 1) { + // /* + // * + // 只有当前ACPI版本大于1时,我们才使用FADT的IAPC_BOOT_ARCH去判断8042是否存在。 + // * 这是一个坑,在ACPI v1中,这个字段是reserved!而这及至ACPI + // v2才出现。 + // * 需要注意:Bochs 和 QEMU 使用的是ACPI v1,而非 v2 + // * (virtualbox好像是v4) + // * + // * (2022/6/29) + // * + // QEMU在7.0.0版本中,修复了FADT::IAPC_BOOT无法正确提供关于i8042的信息的bug + // * https://wiki.qemu.org/ChangeLog/7.0#ACPI_.2F_SMBIOS + // * + // * + // 请看Bochs的bios源码(QEMU的BIOS其实是照抄bochs的,所以也是一个德行。。): + // * + // https://bochs.sourceforge.io/cgi-bin/lxr/source/bios/rombios32.c#L1314 + // */ + // if (!(acpi_ctx->fadt.boot_arch & IAPC_ARCH_8042)) { + // kprintf(KERROR "not found\n"); + // // FUTURE: Some alternative fallback on this? Check PCI bus for + // USB + // // controller instead? + // return; + // } + // } else { + // kprintf(KWARN "outdated FADT used, assuming exists.\n"); + // } char result; @@ -157,7 +164,7 @@ ps2_kbd_init() ps2_post_cmd(PS2_PORT_CTRL_CMDREG, PS2_CMD_PORT2_DISABLE, PS2_NO_ARG); // 2、清空控制器缓冲区 - io_inb(PS2_PORT_ENC_DATA); + port_rdbyte(PS2_PORT_ENC_DATA); // 3、屏蔽所有PS/2设备(端口1&2)IRQ,并且禁用键盘键码转换功能 result = ps2_issue_cmd(PS2_CMD_READ_CFG, PS2_NO_ARG); @@ -298,14 +305,14 @@ intr_ps2_kbd_handler(const isr_param* param) { // This is important! Don't believe me? try comment it out and run on Bochs! - // while (!(io_inb(PS2_PORT_CTRL_STATUS) & PS2_STATUS_OFULL)) + // while (!(port_rdbyte(PS2_PORT_CTRL_STATUS) & PS2_STATUS_OFULL)) // ; // I know you are tempting to move this chunk after the keyboard state // check. But DO NOT. This chunk is in right place and right order. Moving // it at your own risk This is to ensure we've cleared the output buffer // everytime, so it won't pile up across irqs. - u8_t scancode = io_inb(PS2_PORT_ENC_DATA); + u8_t scancode = port_rdbyte(PS2_PORT_ENC_DATA); kbd_keycode_t key; /* @@ -409,10 +416,10 @@ ps2_issue_cmd(char cmd, u16_t arg) // 等待PS/2控制器返回。通过轮询(polling)状态寄存器的 bit 0 // 如置位,则表明返回代码此时就在 0x60 IO口上等待读取。 - while (!(io_inb(PS2_PORT_CTRL_STATUS) & PS2_STATUS_OFULL)) + while (!(port_rdbyte(PS2_PORT_CTRL_STATUS) & PS2_STATUS_OFULL)) ; - return io_inb(PS2_PORT_ENC_CMDREG); + return port_rdbyte(PS2_PORT_ENC_CMDREG); } static u8_t @@ -432,18 +439,18 @@ static void ps2_post_cmd(u8_t port, char cmd, u16_t arg) { // 等待PS/2输入缓冲区清空,这样我们才可以写入命令 - while (io_inb(PS2_PORT_CTRL_STATUS) & PS2_STATUS_IFULL) + while (port_rdbyte(PS2_PORT_CTRL_STATUS) & PS2_STATUS_IFULL) ; - io_outb(port, cmd); - io_delay(PS2_DELAY); + port_wrbyte(port, cmd); + port_delay(PS2_DELAY); if (!(arg & PS2_NO_ARG)) { // 所有参数一律通过0x60传入。 - while (io_inb(PS2_PORT_CTRL_STATUS) & PS2_STATUS_IFULL) + while (port_rdbyte(PS2_PORT_CTRL_STATUS) & PS2_STATUS_IFULL) ; - io_outb(PS2_PORT_ENC_CMDREG, (u8_t)(arg & 0x00ff)); - io_delay(PS2_DELAY); + port_wrbyte(PS2_PORT_ENC_CMDREG, (u8_t)(arg & 0x00ff)); + port_delay(PS2_DELAY); } } @@ -454,8 +461,8 @@ ps2_issue_dev_cmd(char cmd, u16_t arg) // 等待PS/2控制器返回。通过轮询(polling)状态寄存器的 bit 0 // 如置位,则表明返回代码此时就在 0x60 IO口上等待读取。 - while (!(io_inb(PS2_PORT_CTRL_STATUS) & PS2_STATUS_OFULL)) + while (!(port_rdbyte(PS2_PORT_CTRL_STATUS) & PS2_STATUS_OFULL)) ; - return io_inb(PS2_PORT_ENC_CMDREG); + return port_rdbyte(PS2_PORT_ENC_CMDREG); } \ No newline at end of file diff --git a/lunaix-os/kernel/peripheral/serial.c b/lunaix-os/kernel/peripheral/serial.c index 69fb290..516d569 100644 --- a/lunaix-os/kernel/peripheral/serial.c +++ b/lunaix-os/kernel/peripheral/serial.c @@ -1,7 +1,7 @@ #include -#include #include #include +#include LOG_MODULE("UART") @@ -9,30 +9,30 @@ void serial_init_port(ptr_t port) { // disable interrupt, use irq instead - io_outb(COM_RIE(port), 0); + port_wrbyte(COM_RIE(port), 0); // baud rate config (DLAB = 1) - io_outb(COM_RCLINE(port), 0x80); - io_outb(COM_RRXTX(port), BAUD_9600); - io_outb(COM_RIE(port), 0); + port_wrbyte(COM_RCLINE(port), 0x80); + port_wrbyte(COM_RRXTX(port), BAUD_9600); + port_wrbyte(COM_RIE(port), 0); // transmission size = 7bits, no parity, 1 stop bits - io_outb(COM_RCLINE(port), 0x2); + port_wrbyte(COM_RCLINE(port), 0x2); // rx trigger level = 14, clear rx/tx buffer, enable buffer - io_outb(COM_RCFIFO(port), 0xcf); + port_wrbyte(COM_RCFIFO(port), 0xcf); - io_outb(COM_RCMODEM(port), 0x1e); + port_wrbyte(COM_RCMODEM(port), 0x1e); - io_outb(COM_RRXTX(port), 0xaa); + port_wrbyte(COM_RRXTX(port), 0xaa); - if (io_inb(COM_RRXTX(port)) != 0xaa) { + if (port_rdbyte(COM_RRXTX(port)) != 0xaa) { kprintf(KWARN "port.%p: faulty\n", port); return; } - io_outb(COM_RCMODEM(port), 0xf); - io_outb(COM_RIE(port), 0x1); + port_wrbyte(COM_RCMODEM(port), 0xf); + port_wrbyte(COM_RIE(port), 0x1); kprintf("port.%p: ok\n", port); } @@ -48,10 +48,10 @@ serial_init() char serial_rx_byte(ptr_t port) { - while (!(io_inb(COM_RSLINE(port)) & 0x01)) + while (!(port_rdbyte(COM_RSLINE(port)) & 0x01)) ; - return io_inb(COM_RRXTX(port)); + return port_rdbyte(COM_RRXTX(port)); } void @@ -65,10 +65,10 @@ serial_rx_buffer(ptr_t port, char* data, size_t len) void serial_tx_byte(ptr_t port, char data) { - while (!(io_inb(COM_RSLINE(port)) & 0x20)) + while (!(port_rdbyte(COM_RSLINE(port)) & 0x20)) ; - io_outb(COM_RRXTX(port), data); + port_wrbyte(COM_RRXTX(port), data); } void @@ -82,21 +82,21 @@ serial_tx_buffer(ptr_t port, char* data, size_t len) void serial_clear_fifo(ptr_t port) { - io_outb(COM_RIE(port), 0x0); - io_outb(COM_RCFIFO(port), 0x00); + port_wrbyte(COM_RIE(port), 0x0); + port_wrbyte(COM_RCFIFO(port), 0x00); - io_outb(COM_RCFIFO(port), 0xcf); - io_outb(COM_RIE(port), 0x1); + port_wrbyte(COM_RCFIFO(port), 0xcf); + port_wrbyte(COM_RIE(port), 0x1); } void serial_disable_irq(ptr_t port) { - io_outb(COM_RIE(port), 0x0); + port_wrbyte(COM_RIE(port), 0x0); } void serial_enable_irq(ptr_t port) { - io_outb(COM_RIE(port), 0x1); + port_wrbyte(COM_RIE(port), 0x1); } \ No newline at end of file diff --git a/lunaix-os/kernel/proc0.c b/lunaix-os/kernel/proc0.c index 221ec23..64dbcd9 100644 --- a/lunaix-os/kernel/proc0.c +++ b/lunaix-os/kernel/proc0.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -21,12 +22,7 @@ #include #include -#include -#include #include -#include - -#include #include @@ -35,15 +31,6 @@ LOG_MODULE("PROC0") void init_platform(); -void -lock_reserved_memory(); - -void -unlock_reserved_memory(); - -void -__do_reserved_memory(int unlock); - int mount_bootmedium() { @@ -90,6 +77,12 @@ fail: void __proc0() { + /* + * We must defer boot code/data cleaning after we successfully escape that + * area + */ + boot_cleanup(); + init_platform(); init_proc_user_space(__current); @@ -102,11 +95,6 @@ __proc0() } } -extern u8_t __kernel_start; /* link/linker.ld */ -extern u8_t __kernel_end; /* link/linker.ld */ -extern u8_t __init_hhk_end; /* link/linker.ld */ -extern multiboot_info_t* _k_init_mb_info; /* k_init.c */ - void init_platform() { @@ -114,114 +102,20 @@ init_platform() __VERSION__, __TIME__); - // 锁定所有系统预留页(内存映射IO,ACPI之类的),并且进行1:1映射 - lock_reserved_memory(); + twifs_register_plugins(); - // firmware - acpi_init(_k_init_mb_info); - - // die - apic_init(); - ioapic_init(); + /* we must start probing pci after all drivers are registered! */ + pci_load_devices(); // debugger serial_init(); sdbg_init(); - // timers & clock - rtc_init(); - timer_init(SYS_TIMER_FREQUENCY_HZ); - clock_init(); - + // FIXME ps2 kbd is x86 PC specific, not here. // peripherals & chipset features ps2_kbd_init(); - block_init(); - ahci_init(); - - pci_init(); // console console_start_flushing(); console_flush(); - - // expose cake allocator states to vfs - cake_export(); - - unlock_reserved_memory(); - - // clean up - for (size_t i = 0; i < (ptr_t)(&__init_hhk_end); i += PG_SIZE) { - vmm_del_mapping(VMS_SELF, (ptr_t)i); - pmm_free_page(KERNEL_PID, (ptr_t)i); - } -} - -void -lock_reserved_memory() -{ - __do_reserved_memory(0); -} - -void -unlock_reserved_memory() -{ - __do_reserved_memory(1); -} - -void -__do_reserved_memory(int unlock) -{ - multiboot_memory_map_t* mmaps = - (multiboot_memory_map_t*)_k_init_mb_info->mmap_addr; - - size_t map_size = - _k_init_mb_info->mmap_length / sizeof(multiboot_memory_map_t); - - // v_mapping mapping; - for (unsigned int i = 0; i < map_size; i++) { - multiboot_memory_map_t mmap = mmaps[i]; - ptr_t pa = PG_ALIGN(mmap.addr_low); - - if (mmap.type == MULTIBOOT_MEMORY_AVAILABLE || pa <= MEM_4MB) { - // Don't fuck up our kernel code or any free area! - continue; - } - - size_t pg_num = CEIL(mmap.len_low, PG_SIZE_BITS); - size_t j = 0; - - if (!unlock) { - kprintf("mem: freeze: %p..%p type=%x\n", - pa, - pa + pg_num * PG_SIZE, - mmap.type); - - for (; j < pg_num; j++) { - ptr_t _pa = pa + (j << PG_SIZE_BITS); - if (_pa >= KERNEL_MM_BASE) { - // Don't fuck up our kernel space! - break; - } - vmm_set_mapping(VMS_SELF, _pa, _pa, PG_PREM_R, VMAP_NULL); - pmm_mark_page_occupied( - KERNEL_PID, _pa >> PG_SIZE_BITS, PP_FGLOCKED); - } - - // Save the progress for later unmapping. - mmaps[i].len_low = j * PG_SIZE; - } else { - kprintf("mem: reclaim: %p..%p type=%x\n", - pa, - pa + pg_num * PG_SIZE, - mmap.type); - - for (; j < pg_num; j++) { - ptr_t _pa = pa + (j << PG_SIZE_BITS); - vmm_del_mapping(VMS_SELF, _pa); - if (mmap.type == MULTIBOOT_MEMORY_ACPI_RECLAIMABLE) { - pmm_mark_page_free(_pa >> PG_SIZE_BITS); - } - } - } - } } \ No newline at end of file diff --git a/lunaix-os/kernel/process/process.c b/lunaix-os/kernel/process/process.c index f500cbe..2407ecf 100644 --- a/lunaix-os/kernel/process/process.c +++ b/lunaix-os/kernel/process/process.c @@ -11,7 +11,9 @@ #include #include #include + #include +#include LOG_MODULE("PROC") @@ -24,7 +26,7 @@ __dup_pagetable(pid_t pid, ptr_t mount_point) x86_page_table* ptd = (x86_page_table*)PG_MOUNT_1; x86_page_table* pptd = (x86_page_table*)(mount_point | (0x3FF << 12)); - size_t kspace_l1inx = L1_INDEX(KERNEL_MM_BASE); + size_t kspace_l1inx = L1_INDEX(KERNEL_EXEC); for (size_t i = 0; i < PG_MAX_ENTRIES - 1; i++) { @@ -63,7 +65,7 @@ __del_pagetable(pid_t pid, ptr_t mount_point) x86_page_table* pptd = (x86_page_table*)(mount_point | (0x3FF << 12)); // only remove user address space - for (size_t i = 0; i < L1_INDEX(KERNEL_MM_BASE); i++) { + for (size_t i = 0; i < L1_INDEX(KERNEL_EXEC); i++) { x86_pte_t ptde = pptd->entry[i]; if (!ptde || !(ptde & PG_PRESENT)) { continue; @@ -249,7 +251,7 @@ dup_proc() return pcb->pid; } -extern void __kernel_end; +extern void __kexec_end; void copy_kernel_stack(struct proc_info* proc, ptr_t usedMnt) diff --git a/lunaix-os/kernel/process/sched.c b/lunaix-os/kernel/process/sched.c index ec5d6c0..651ab0e 100644 --- a/lunaix-os/kernel/process/sched.c +++ b/lunaix-os/kernel/process/sched.c @@ -1,8 +1,9 @@ #include #include +#include -#include #include +#include #include #include @@ -79,20 +80,8 @@ run(struct proc_info* proc) { proc->state = PS_RUNNING; - /* - 将tss.esp0设置为上次调度前的esp值。 - 当处理信号时,上下文信息是不会恢复的,而是保存在用户栈中,然后直接跳转进位于用户空间的sig_wrapper进行 - 信号的处理。当用户自定义的信号处理函数返回时,sigreturn的系统调用才开始进行上下文的恢复(或者说是进行 - 另一次调度。 - 由于这中间没有进行地址空间的交换,所以第二次跳转使用的是同一个内核栈,而之前默认tss.esp0的值是永远指向最顶部 - 这样一来就有可能会覆盖更早的上下文信息(比如嵌套的信号捕获函数) - */ - - apic_done_servicing(); - - asm volatile("pushl %0\n" - "jmp switch_to\n" ::"r"(proc) - : "memory"); // kernel/asm/x86/interrupt.S + intc_notify_eos(0); + switch_context(proc); } int @@ -221,6 +210,9 @@ __DEFINE_LXSYSCALL1(unsigned int, sleep, unsigned int, seconds) return 0; } +// FIXME issue with alarm, paused parent process never got wake up, check what +// has been fucked up by refactoring. + __DEFINE_LXSYSCALL1(unsigned int, alarm, unsigned int, seconds) { time_t prev_ddl = __current->sleep.alarm_time; diff --git a/lunaix-os/kernel/spike.c b/lunaix-os/kernel/spike.c index 231b85d..67f9abe 100644 --- a/lunaix-os/kernel/spike.c +++ b/lunaix-os/kernel/spike.c @@ -1,6 +1,6 @@ -#include #include #include +#include static char buffer[1024]; @@ -18,9 +18,9 @@ __assert_fail(const char* expr, const char* file, unsigned int line) DO_SPIN // never reach } -void +void noret panick(const char* msg) -{ +{ cpu_trap_panic(msg); DO_SPIN } diff --git a/lunaix-os/kernel/syscall.c b/lunaix-os/kernel/syscall.c deleted file mode 100644 index 1c0110d..0000000 --- a/lunaix-os/kernel/syscall.c +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include -#include -#include -#include -#include - -LOG_MODULE("SYSCALL") - -extern void -syscall_hndlr(const isr_param* param); - -void -syscall_install() -{ - isrm_bindiv(LUNAIX_SYS_CALL, syscall_hndlr); -} \ No newline at end of file diff --git a/lunaix-os/kernel/time/clock.c b/lunaix-os/kernel/time/clock.c index e91be19..726e333 100644 --- a/lunaix-os/kernel/time/clock.c +++ b/lunaix-os/kernel/time/clock.c @@ -1,21 +1,16 @@ -#include +#include +#include #include #include #include -#include #include -static volatile time_t sys_time; - -void -clock_systime_counter(void* arg); - void __clock_read_systime(struct twimap* map) { - time_t save = sys_time; - twimap_printf(map, "%u", save); + ticks_t sys_time = clock_systime(); + twimap_printf(map, "%u", sys_time); } void @@ -36,9 +31,7 @@ __clock_read_datetime(struct twimap* map) void __clock_read_unix(struct twimap* map) { - datetime_t dt; - clock_walltime(&dt); - twimap_printf(map, "%u", clock_tounixtime(&dt)); + twimap_printf(map, "%u", clock_unixtime()); } void @@ -56,83 +49,31 @@ clock_build_mapping() map = twifs_mapping(root, NULL, "datetime"); map->read = __clock_read_datetime; } +EXPORT_TWIFS_PLUGIN(sys_clock, clock_build_mapping); void clock_init() { - if (!timer_context()) { - panick("Systimer not initialized"); - } - - // 系统计时器每毫秒累加。 - timer_run_ms(1, clock_systime_counter, NULL, TIMER_MODE_PERIODIC); - - clock_build_mapping(); -} - -void -clock_systime_counter(void* arg) -{ - sys_time++; -} - -int -clock_datatime_eq(datetime_t* a, datetime_t* b) -{ - return a->year == b->year && a->month == b->month && a->day == b->day && - a->weekday == b->weekday && a->minute == b->minute && - a->second == b->second; -} - -void -clock_walltime(datetime_t* datetime) -{ - datetime_t current; - - do { - while (rtc_read_reg(RTC_REG_A) & 0x80) - ; - memcpy(¤t, datetime, sizeof(datetime_t)); - - datetime->year = rtc_read_reg(RTC_REG_YRS); - datetime->month = rtc_read_reg(RTC_REG_MTH); - datetime->day = rtc_read_reg(RTC_REG_DAY); - datetime->weekday = rtc_read_reg(RTC_REG_WDY); - datetime->hour = rtc_read_reg(RTC_REG_HRS); - datetime->minute = rtc_read_reg(RTC_REG_MIN); - datetime->second = rtc_read_reg(RTC_REG_SEC); - } while (!clock_datatime_eq(datetime, ¤t)); - - u8_t regbv = rtc_read_reg(RTC_REG_B); - - // Convert from bcd to binary when needed - if (!RTC_BIN_ENCODED(regbv)) { - datetime->year = bcd2dec(datetime->year); - datetime->month = bcd2dec(datetime->month); - datetime->day = bcd2dec(datetime->day); - datetime->hour = bcd2dec(datetime->hour); - datetime->minute = bcd2dec(datetime->minute); - datetime->second = bcd2dec(datetime->second); - } - - // To 24 hour format - if (!RTC_24HRS_ENCODED(regbv) && (datetime->hour >> 7)) { - datetime->hour = 12 + (datetime->hour & 0x80); - } - - datetime->year += RTC_CURRENT_CENTRY * 100; + hwrtc_init(); } time_t clock_unixtime() { datetime_t dt; - clock_walltime(&dt); - return clock_tounixtime(&dt); + hwrtc_walltime(&dt); + return datetime_tounix(&dt); } time_t clock_systime() { - return sys_time; + ticks_t t = hwtimer_current_systicks(); + return t / hwtimer_base_frequency(); +} + +void +clock_walltime(datetime_t* datetime) +{ + current_rtc->get_walltime(current_rtc, datetime); } \ No newline at end of file diff --git a/lunaix-os/kernel/time/timer.c b/lunaix-os/kernel/time/timer.c index 61f6d41..8f368df 100644 --- a/lunaix-os/kernel/time/timer.c +++ b/lunaix-os/kernel/time/timer.c @@ -10,10 +10,7 @@ * */ #include -#include -#include -#include #include #include #include @@ -21,35 +18,20 @@ #include #include -#include - -#define LVT_ENTRY_TIMER(vector, mode) (LVT_DELIVERY_FIXED | mode | vector) +#include LOG_MODULE("TIMER"); static void -temp_intr_routine_rtc_tick(const isr_param* param); - -static void -temp_intr_routine_apic_timer(const isr_param* param); - -static void -timer_update(const isr_param* param); +timer_update(); static volatile struct lx_timer_context* timer_ctx = NULL; -// Don't optimize them! Took me an half hour to figure that out... - -static volatile u32_t rtc_counter = 0; -static volatile u8_t apic_timer_done = 0; - static volatile u32_t sched_ticks = 0; static volatile u32_t sched_ticks_counter = 0; static struct cake_pile* timer_pile; -#define APIC_CALIBRATION_CONST 0x100000 - void timer_init_context() { @@ -64,92 +46,15 @@ timer_init_context() } void -timer_init(u32_t frequency) +timer_init() { timer_init_context(); - cpu_disable_interrupt(); - - // Setup APIC timer - - // Remap the IRQ 8 (rtc timer's vector) to RTC_TIMER_IV in ioapic - // (Remarks IRQ 8 is pin INTIN8) - // See IBM PC/AT Technical Reference 1-10 for old RTC IRQ - // See Intel's Multiprocessor Specification for IRQ - IOAPIC INTIN - // mapping config. - - // grab ourselves these irq numbers - u32_t iv_rtc = isrm_bindirq(PC_AT_IRQ_RTC, temp_intr_routine_rtc_tick); - u32_t iv_timer = isrm_ivexalloc(temp_intr_routine_apic_timer); - - // Setup a one-shot timer, we will use this to measure the bus speed. So we - // can then calibrate apic timer to work at *nearly* accurate hz - apic_write_reg(APIC_TIMER_LVT, - LVT_ENTRY_TIMER(iv_timer, LVT_TIMER_ONESHOT)); - - // Set divider to 64 - apic_write_reg(APIC_TIMER_DCR, APIC_TIMER_DIV64); - - /* - Timer calibration process - measure the APIC timer base frequency - - step 1: setup a temporary isr for RTC timer which trigger at each tick - (1024Hz) - step 2: setup a temporary isr for #APIC_TIMER_IV - step 3: setup the divider, APIC_TIMER_DCR - step 4: Startup RTC timer - step 5: Write a large value, v, to APIC_TIMER_ICR to start APIC timer - (this must be followed immediately after step 4) step 6: issue a write to - EOI and clean up. - - When the APIC ICR counting down to 0 #APIC_TIMER_IV triggered, save the - rtc timer's counter, k, and disable RTC timer immediately (although the - RTC interrupts should be blocked by local APIC as we are currently busy - on handling #APIC_TIMER_IV) - - So the apic timer frequency F_apic in Hz can be calculate as - v / F_apic = k / 1024 - => F_apic = v / k * 1024 - - */ - -#ifdef __LUNAIXOS_DEBUG__ - if (frequency < 1000) { - kprintf(KWARN "Frequency too low. Millisecond timer might be dodgy."); - } -#endif + hwtimer_init(SYS_TIMER_FREQUENCY_HZ, timer_update); - timer_ctx->base_frequency = 0; - rtc_counter = 0; - apic_timer_done = 0; + timer_ctx->base_frequency = hwtimer_base_frequency(); - rtc_enable_timer(); // start RTC timer - apic_write_reg(APIC_TIMER_ICR, APIC_CALIBRATION_CONST); // start APIC timer - - // enable interrupt, just for our RTC start ticking! - cpu_enable_interrupt(); - - wait_until(apic_timer_done); - - assert_msg(timer_ctx->base_frequency, "Fail to initialize timer (NOFREQ)"); - - kprintf( - KINFO "hw: %u Hz; os: %u Hz\n", timer_ctx->base_frequency, frequency); - - timer_ctx->running_frequency = frequency; - timer_ctx->tphz = timer_ctx->base_frequency / frequency; - - // cleanup - isrm_ivfree(iv_timer); - isrm_ivfree(iv_rtc); - - apic_write_reg( - APIC_TIMER_LVT, - LVT_ENTRY_TIMER(isrm_ivexalloc(timer_update), LVT_TIMER_PERIODIC)); - - apic_write_reg(APIC_TIMER_ICR, timer_ctx->tphz); - - sched_ticks = timer_ctx->running_frequency / 1000 * SCHED_TIME_SLICE; + sched_ticks = SYS_TIMER_FREQUENCY_HZ / 1000 * SCHED_TIME_SLICE; sched_ticks_counter = 0; } @@ -159,8 +64,8 @@ timer_run_second(u32_t second, void* payload, u8_t flags) { - return timer_run( - second * timer_ctx->running_frequency, callback, payload, flags); + ticks_t t = hwtimer_to_ticks(second, TIME_SEC); + return timer_run(t, callback, payload, flags); } struct lx_timer* @@ -169,10 +74,8 @@ timer_run_ms(u32_t millisecond, void* payload, u8_t flags) { - return timer_run(timer_ctx->running_frequency / 1000 * millisecond, - callback, - payload, - flags); + ticks_t t = hwtimer_to_ticks(millisecond, TIME_MS); + return timer_run(t, callback, payload, flags); } struct lx_timer* @@ -195,7 +98,7 @@ timer_run(ticks_t ticks, void (*callback)(void*), void* payload, u8_t flags) } static void -timer_update(const isr_param* param) +timer_update() { struct lx_timer *pos, *n; struct lx_timer* timer_list_head = timer_ctx->active_timers; @@ -224,26 +127,6 @@ timer_update(const isr_param* param) } } -static void -temp_intr_routine_rtc_tick(const isr_param* param) -{ - rtc_counter++; - - // dummy read on register C so RTC can send anther interrupt - // This strange behaviour observed in virtual box & bochs - (void)rtc_read_reg(RTC_REG_C); -} - -static void -temp_intr_routine_apic_timer(const isr_param* param) -{ - timer_ctx->base_frequency = - APIC_CALIBRATION_CONST / rtc_counter * RTC_TIMER_BASE_FREQUENCY; - apic_timer_done = 1; - - rtc_disable_timer(); -} - struct lx_timer_context* timer_context() { diff --git a/lunaix-os/kernel/tty/tty.c b/lunaix-os/kernel/tty/tty.c index 4c9631c..e90899b 100644 --- a/lunaix-os/kernel/tty/tty.c +++ b/lunaix-os/kernel/tty/tty.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -6,6 +5,8 @@ #include #include +#include + vga_attribute* tty_vga_buffer; vga_attribute tty_theme_color = VGA_COLOR_BLACK; @@ -26,11 +27,11 @@ tty_init(void* vga_buf) tty_clear(); - io_outb(0x3D4, 0x0A); - io_outb(0x3D5, (io_inb(0x3D5) & 0xC0) | 13); + port_wrbyte(0x3D4, 0x0A); + port_wrbyte(0x3D5, (port_rdbyte(0x3D5) & 0xC0) | 13); - io_outb(0x3D4, 0x0B); - io_outb(0x3D5, (io_inb(0x3D5) & 0xE0) | 15); + port_wrbyte(0x3D4, 0x0B); + port_wrbyte(0x3D5, (port_rdbyte(0x3D5) & 0xE0) | 15); } void @@ -40,10 +41,10 @@ tty_set_cursor(u8_t x, u8_t y) x = y = 0; } u32_t pos = y * TTY_WIDTH + x; - io_outb(0x3D4, 14); - io_outb(0x3D5, pos / 256); - io_outb(0x3D4, 15); - io_outb(0x3D5, pos % 256); + port_wrbyte(0x3D4, 14); + port_wrbyte(0x3D5, pos / 256); + port_wrbyte(0x3D4, 15); + port_wrbyte(0x3D5, pos % 256); } void diff --git a/lunaix-os/link/linker.ld b/lunaix-os/link/linker.ld index 937777b..71bc151 100644 --- a/lunaix-os/link/linker.ld +++ b/lunaix-os/link/linker.ld @@ -11,35 +11,39 @@ SECTIONS { . = 0x100000; /* 这里是我们的高半核初始化代码段和数据段 */ - .hhk_init_text BLOCK(4K) : { + .boot.text BLOCK(4K) : { *(.multiboot) - *(.hhk_init_text) + *(.boot.text) } - .hhk_init_bss BLOCK(4K) : { - *(.hhk_init_bss) + .boot.bss BLOCK(4K) : { + *(.boot.bss) } - .hhk_init_data BLOCK(4K) : { - *(.hhk_init_data) + .boot.data BLOCK(4K) : { + *(.boot.data) } - .hhk_init_rodata BLOCK(4K) : { - *(.hhk_init_rodata) + .boot.rodata BLOCK(4K) : { + *(.boot.rodata) } - __init_hhk_end = ALIGN(4K); + + .boot.bss BLOCK(4K) : { + *(.boot.rodata) + } + __kexec_boot_end = ALIGN(4K); /* Relocation of our higher half kernel */ . += 0xC0000000; /* 好了,我们的内核…… */ .text BLOCK(4K) : AT ( ADDR(.text) - 0xC0000000 ) { - __kernel_start = .; - PROVIDE(__ktext_start = .); + __kexec_start = .; + PROVIDE(__kexec_text_start = .); *(.text) - PROVIDE(__ktext_end = .); + PROVIDE(__kexec_text_end = .); } .data BLOCK(4K) : AT ( ADDR(.data) - 0xC0000000 ) { @@ -54,9 +58,29 @@ SECTIONS { *(.kpg) } + . = ALIGN(4K); + + /* for generated array, we align to address line size */ + + .lga BLOCK(4K) : AT ( ADDR(.lga) - 0xC0000000 ) { + PROVIDE(__lga_twiplugin_inits_start = .); + + KEEP(*(.lga.twiplugin_inits)); + + PROVIDE(__lga_twiplugin_inits_end = .); + + /* ---- */ + + PROVIDE(__lga_pci_dev_drivers_start = .); + + KEEP(*(.lga.pci_dev_drivers)); + + PROVIDE(__lga_pci_dev_drivers_end = .); + } + .bss BLOCK(4K) : AT ( ADDR(.bss) - 0xC0000000 ) { *(.bss) } - __kernel_end = ALIGN(4K); + __kexec_end = ALIGN(4K); } \ No newline at end of file diff --git a/lunaix-os/makefile b/lunaix-os/makefile index bb105d4..e8deacf 100644 --- a/lunaix-os/makefile +++ b/lunaix-os/makefile @@ -38,7 +38,7 @@ $(kbuild_dir): @mkdir -p $(os_img_dir)/boot/grub @mkdir -p $(os_img_dir)/usr -export BUILD_DIR=$(kbuild_dir) +export BUILD_DIR=$(kbin_dir) export BUILD_NAME=$(kbin) $(kbin): $(call status,TASK,$(notdir $@)) @@ -48,7 +48,7 @@ $(kimg): usr/build $(kbin) $(call status,TASK,$(notdir $@)) @./config-grub.sh ${OS_NAME} $(os_img_dir)/boot/grub/grub.cfg @cp -r usr/build/* $(os_img_dir)/usr - @cp $(kbin) $(os_img_dir)/boot + @cp -r $(kbin_dir)/* $(os_img_dir)/boot @grub-mkrescue -o $(kimg) $(os_img_dir) -- -volid "$(OS_ID) $(OS_VER)" -system_id "$(OS_NAME)" usr/build: user @@ -91,11 +91,11 @@ debug-qemu: all-debug @qemu-system-i386 $(call get_qemu_options,$(kimg)) @sleep 1 @$(QEMU_MON_TERM) -- telnet 127.0.0.1 $(QEMU_MON_PORT) - @gdb -s $(BUILD_DIR)/kernel.dbg -ex "target remote localhost:1234" + @gdb -s $(kbuild_dir)/kernel.dbg -ex "target remote localhost:1234" debug-qemu-vscode: all-debug @i686-elf-objcopy --only-keep-debug $(kbin) $(kbuild_dir)/kernel.dbg - @qemu-system-i386 $(QEMU_OPTIONS) + @qemu-system-i386 $(call get_qemu_options,$(kimg)) @sleep 0.5 @telnet 127.0.0.1 $(QEMU_MON_PORT) diff --git a/lunaix-os/makeinc/toolchain.mkinc b/lunaix-os/makeinc/toolchain.mkinc index fffd182..b629d6f 100644 --- a/lunaix-os/makeinc/toolchain.mkinc +++ b/lunaix-os/makeinc/toolchain.mkinc @@ -1,11 +1,12 @@ CC := i686-elf-gcc AS := i686-elf-as AR := i686-elf-ar +PY := python ARCH_OPT := -D__ARCH_IA32 O := -O2 -W := -Wall -Wextra -Wno-unknown-pragmas \ +W := -Wall -Wextra -Werror -Wno-unknown-pragmas \ -Wno-unused-function \ -Wno-unused-variable\ -Wno-unused-but-set-variable \ diff --git a/lunaix-os/scripts/expand.py b/lunaix-os/scripts/expand.py index cd62164..041bb78 100644 --- a/lunaix-os/scripts/expand.py +++ b/lunaix-os/scripts/expand.py @@ -269,12 +269,20 @@ class MemoryMapObject(DataObject): super().__init__("", record) def _parse(self, record): - if "granule" in self._record: - self.__g = MemoryMapObject.GranuleObject(self._record["granule"]) - if "regions" in self._record: - self.__regions = ArrayObject(self._record["regions"]) - if "width" in self._record: - self.__width = DataObject.create("width", self._record["width"]) + for k, v in record.items(): + if k.startswith("$"): + self.ctrl_field[k.strip("$")] = FieldType.create(k, v) + elif k.startswith("@"): + self.ctrl_field[k.strip("@")] = DataObject.create(k, v) + + if "granule" in record: + self.__g = MemoryMapObject.GranuleObject(record["granule"]) + + if "regions" in record: + self.__regions = ArrayObject(record["regions"]) + + if "width" in record: + self.__width = DataObject.create("width", record["width"]) def __process(self, start_addr, idx, regions, size_lookahead = False): if idx >= len(regions): @@ -282,8 +290,8 @@ class MemoryMapObject(DataObject): e = regions[idx] - if "boundary" in e: - b = e["boundary"] - 1 + if "block" in e: + b = e["block"] - 1 start_addr = (start_addr + b) & ~b if "start" not in e: @@ -305,6 +313,8 @@ class MemoryMapObject(DataObject): return start_addr def expand(self, param={}): + super().expand(param) + g = self.__g.expand(param) param["granule"] = g diff --git a/lunaix-os/scripts/syms_export.py b/lunaix-os/scripts/syms_export.py new file mode 100644 index 0000000..af5d901 --- /dev/null +++ b/lunaix-os/scripts/syms_export.py @@ -0,0 +1,86 @@ +import subprocess +import math +import re + +sym_line = re.compile(r"^(?P[0-9a-f]+)\s[a-z]\s+F\s+\.[a-z._]+\s+[0-9a-f]+(?P