feat: linker generated array to free up the need of those nasty explicit invocation init_* functions
],
"compilerArgs": [
"-ffreestanding",
- "-D__ARCH_IA32",
+ "-D__ARCH__=i386",
"-D__LUNAIXOS_DEBUG__",
"-include flags.h"
],
"type": "gdb",
"request": "attach",
"name": "LunaixOS",
- "executable": "${workspaceRoot}/build/bin/lunaix.bin",
+ "executable": "${workspaceRoot}/build/bin/kernel.bin",
"target": ":1234",
"remote": true,
"cwd": "${workspaceRoot}",
menuentry "$_OS_NAME" {
multiboot /boot/kernel.bin
+ module /boot/modksyms modksyms
}
\ No newline at end of file
--- /dev/null
+#include <hal/apic_timer.h>
+#include <hal/rtc/mc146818a.h>
+
+#include <hal/hwrtc.h>
+#include <hal/hwtimer.h>
+
+#include <lunaix/isrm.h>
+#include <lunaix/spike.h>
+
+#include <sys/i386_intr.h>
+#include <sys/interrupts.h>
+
+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
.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:
.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
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
/*
基本的映射定义好了,我们可以放心的打开分页了
-#include <sys/boot/multiboot.h>
+#define __BOOT_CODE__
+
#include <lunaix/common.h>
#include <lunaix/mm/page.h>
+#include <sys/boot/bstage.h>
+#include <sys/mm/mempart.h>
+
#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) \
#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
#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)
// 这里是一些计算,主要是计算应当映射进的 页目录 与 页表 的条目索引(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;
// 将内核所需要的页表注册进页目录
}
// 计算内核.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++) {
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
--- /dev/null
+#define __BOOT_CODE__
+
+#include <lunaix/boot_generic.h>
+#include <sys/boot/bstage.h>
+#include <sys/boot/multiboot.h>
+#include <sys/mm/mempart.h>
+
+#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
/* 高半核入口点 - 0xC0000000 */
#define __ASM__
-#include <sys/x86_isa.h>
+#include <sys/abi.h>
.section .text
.global hhk_entry_
/*
欢迎来到虚拟内存的世界! :D
*/
-
+ andl $stack_alignment, %esp
subl $16, %esp
/*
最终还是决定将IDT&GDT的初始化和安装放在这里
这主要是为了保险起见,让GDTR有一个合法的值,否则多咱的粗心大意,容易出#GP
*/
call _init_gdt
+
movl $_gdt, 2(%esp)
movw _gdt_limit, %ax
movw %ax, (%esp)
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)
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
+++ /dev/null
-#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
/* Generated from i386_isrdef.c.j2. Do NOT modify */
-#include "i386_intr.h"
#include <lunaix/types.h>
+#include <sys/i386_intr.h>
#define IDT_INTERRUPT 0x70
#define KERNEL_CS 0x8
-#include <hal/acpi/acpi.h>
-#include <hal/ioapic.h>
-
#include <lunaix/isrm.h>
#include <lunaix/spike.h>
+#include <hal/intc.h>
+
/*
total: 256 ivs
0~31: reserved for sys use (x32)
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);
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;
}
}
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;
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
{
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;
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;
}
{
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;
# 约定
# 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
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)
#include <sys/interrupts.h>
#include <sys/x86_isa.h>
-#include <hal/apic.h>
#include <hal/cpu.h>
+#include <hal/intc.h>
#include <lunaix/isrm.h>
#include <lunaix/mm/page.h>
#include <lunaix/syslog.h>
#include <lunaix/tty/tty.h>
-#include "i386_intr.h"
+#include <sys/i386_intr.h>
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)
{
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
#include <klibc/stdio.h>
-#include <hal/apic.h>
-
-#include "i386_intr.h"
+#include <sys/apic.h>
+#include <sys/i386_intr.h>
LOG_MODULE("INTR")
void
intr_routine_fallback(const isr_param* param)
{
- console_flush();
__print_panic_msg("Unknown Interrupt", param);
+ console_flush();
spin();
}
+++ /dev/null
-#include "gdt.h"
-#include <lunaix/types.h>
-#include <sys/x86_isa.h>
-
-#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
* @copyright Copyright (c) 2022
*
*/
-#include <hal/apic.h>
+
#include <hal/cpu.h>
-#include <hal/pic.h>
-#include <hal/rtc.h>
+#include <hal/intc.h>
+#include <sys/apic.h>
#include <sys/interrupts.h>
#include <lunaix/mm/mmio.h>
#include <lunaix/spike.h>
#include <lunaix/syslog.h>
+#include "pic.h"
+
LOG_MODULE("APIC")
-static volatile uintptr_t _apic_base;
+static volatile ptr_t _apic_base;
void
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
--- /dev/null
+#include <hal/acpi/acpi.h>
+#include <hal/intc.h>
+
+#include <lunaix/common.h>
+#include <lunaix/mm/mmio.h>
+
+#include <sys/interrupts.h>
+#include <sys/ioapic.h>
+
+#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
--- /dev/null
+#include <sys/apic.h>
+#include <sys/pci_hba.h>
+
+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
--- /dev/null
+#include <hal/intc.h>
+#include <sys/apic.h>
+#include <sys/ioapic.h>
+
+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;
+}
"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) \
{ \
#ifndef __LUNAIX_APIC_H
#define __LUNAIX_APIC_H
+#include <hal/intc.h>
#include <lunaix/common.h>
-#include <stdint.h>
+#include <lunaix/types.h>
#define __APIC_BASE_PADDR 0xFEE00000
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 */
--- /dev/null
+#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 */
--- /dev/null
+#ifndef __LUNAIX_IOAPIC_H
+#define __LUNAIX_IOAPIC_H
+
+#include <hal/intc.h>
+
+void
+ioapic_init();
+
+void
+ioapic_irq_remap(struct intc_context*,
+ int irq,
+ int iv,
+ cpu_t dest,
+ u32_t flags);
+
+#endif /* __LUNAIX_IOAPIC_H */
+#ifndef __LUNAIX_MEMPART_H
+#define __LUNAIX_MEMPART_H
/* Physical Adress Space Partition */
/* Generated from mempart.h.j2. Do NOT modify */
#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
#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
--- /dev/null
+#ifndef __LUNAIX_PCI_HBA_H
+#define __LUNAIX_PCI_HBA_H
+
+#include <hal/pci.h>
+#include <lunaix/types.h>
+
+#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 */
-#ifndef __LUNAIX_IO_H
-#define __LUNAIX_IO_H
+#ifndef __LUNAIX_PORT_IO_H
+#define __LUNAIX_PORT_IO_H
#include <lunaix/types.h>
static inline u8_t
-io_inb(int port)
+port_rdbyte(int port)
{
u8_t data;
asm volatile("inb %w1,%0" : "=a"(data) : "d"(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"
}
static inline u16_t
-io_inw(int port)
+port_rdword(int port)
{
u16_t data;
asm volatile("inw %w1,%0" : "=a"(data) : "d"(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"
}
static inline u32_t
-io_inl(int port)
+port_rddword(int port)
{
u32_t data;
asm volatile("inl %w1,%0" : "=a"(data) : "d"(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"
}
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"
}
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"
}
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"
}
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"
"1: dec %0" ::"a"(counter));
}
-#endif /* __LUNAIX_IO_H */
+#endif /* __LUNAIX_PORT_port_H */
// clang-format off
+#define TOTAL_IV 256
+
#define FAULT_DIVISION_ERROR 0
#define INSTR_DEBUG 1
#define INT_NMI 2
#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
--- /dev/null
+#include <lunaix/types.h>
+#include <sys/x86_isa.h>
+
+#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
-#include <sys/interrupts.h>
#include <lunaix/common.h>
#include <lunaix/mm/mm.h>
#include <lunaix/mm/pmm.h>
#include <lunaix/signal.h>
#include <lunaix/status.h>
#include <lunaix/syslog.h>
+#include <sys/interrupts.h>
#include <klibc/string.h>
#include <lunaix/process.h>
+#include <sys/mm/mempart.h>
+#include <sys/x86_isa.h>
+
+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,
+++ /dev/null
-#include <lunaix/common.h>
-#include <lunaix/process.h>
-#include <sys/x86_isa.h>
-
-volatile struct x86_tss _tss = { .link = 0,
- .esp0 = KSTACK_TOP,
- .ss0 = KDATA_SEG };
\ No newline at end of file
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)");
}
u8_t
-acpi_gistranslate(u8_t old_irq)
+acpi_gsimap(u8_t old_irq)
{
if (old_irq >= 24) {
return 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);
break;
}
}
-#endif
return rsdp;
}
\ No newline at end of file
#include <hal/ahci/hba.h>
#include <hal/ahci/sata.h>
#include <hal/ahci/scsi.h>
-
#include <hal/pci.h>
+
+#include <sys/pci_hba.h>
+#include <sys/port_io.h>
+
#include <klibc/string.h>
#include <lunaix/block.h>
#include <lunaix/isrm.h>
LOG_MODULE("AHCI")
-struct llist_header ahcis;
+DEFINE_LLIST(ahcis);
static char sata_ifs[][20] = { "Not detected",
"SATA I (1.5Gbps)",
}
// 如果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)
{
return ahci_drv;
}
+EXPORT_PCI_DEVICE(pci_ahci, AHCI_HBA_CLASS, 0, 0, ahci_driver_init);
void
ahci_register_device(struct hba_device* hbadev)
--- /dev/null
+#include <hal/intc.h>
+#include <lunaix/spike.h>
+
+#include <sys/vectors.h>
+
+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
+++ /dev/null
-#include <sys/interrupts.h>
-#include <hal/acpi/acpi.h>
-#include <hal/ioapic.h>
-#include <lunaix/common.h>
-#include <lunaix/mm/mmio.h>
-
-#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
* @copyright Copyright (c) 2022
*
*/
-#include <hal/acpi/acpi.h>
-#include <hal/apic.h>
#include <hal/pci.h>
+#include <sys/pci_hba.h>
+
#include <klibc/string.h>
#include <lunaix/fs/twifs.h>
#include <lunaix/mm/valloc.h>
}
}
-void
+static void
__pci_read_cspace(struct twimap* map)
{
struct pci_device* pcidev = (struct pci_device*)(map->data);
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*);
twimap_printf(map, "\n");
}
-int
+static int
__pci_bar_gonext(struct twimap* map)
{
if (twimap_index(map, int) >= 5) {
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)
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)
{
}
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
+++ /dev/null
-/**
- * @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 <hal/rtc.h>
-#include <klibc/string.h>
-
-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
--- /dev/null
+#include <hal/hwrtc.h>
+
+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
--- /dev/null
+/**
+ * @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 <lunaix/isrm.h>
+
+#include <hal/rtc/mc146818a.h>
+
+#include <klibc/string.h>
+
+#include <sys/interrupts.h>
+#include <sys/port_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)
+
+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;
+}
--- /dev/null
+#include <hal/apic_timer.h>
+#include <hal/hwrtc.h>
+#include <hal/hwtimer.h>
+
+#include <lunaix/compiler.h>
+#include <lunaix/isrm.h>
+#include <lunaix/spike.h>
+#include <lunaix/syslog.h>
+
+#include <sys/apic.h>
+
+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;
+}
--- /dev/null
+#include <hal/hwtimer.h>
+#include <lunaix/spike.h>
+
+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
#ifndef __LUNAIX_ACPI_ACPI_H
#define __LUNAIX_ACPI_ACPI_H
-#include <sys/boot/multiboot.h>
#include <stddef.h>
#include <stdint.h>
#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
} 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 */
int id;
};
-/**
- * @brief 初始化AHCI与HBA
- *
- */
-void
-ahci_init();
-
void
ahci_parse_dev_info(struct hba_device* dev_info, u16_t* data);
--- /dev/null
+#ifndef __LUNAIX_APIC_TIMER_H
+#define __LUNAIX_APIC_TIMER_H
+
+#include <hal/hwtimer.h>
+
+struct hwtimer_context* apic_hwtimer_context();
+
+#endif /* __LUNAIX_APIC_TIMER_H */
--- /dev/null
+#ifndef __LUNAIX_HWRTC_H
+#define __LUNAIX_HWRTC_H
+
+#include <lunaix/time.h>
+
+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 */
--- /dev/null
+#ifndef __LUNAIX_HWTIMER_H
+#define __LUNAIX_HWTIMER_H
+
+#include <lunaix/time.h>
+#include <lunaix/types.h>
+
+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 */
--- /dev/null
+#ifndef __LUNAIX_INTC_H
+#define __LUNAIX_INTC_H
+
+#include <lunaix/types.h>
+
+#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 */
+++ /dev/null
-#ifndef __LUNAIX_IOAPIC_H
-#define __LUNAIX_IOAPIC_H
-
-#include <stdint.h>
-
-#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 */
#ifndef __LUNAIX_PCI_H
#define __LUNAIX_PCI_H
-#include <hal/io.h>
+#include <lunaix/ds/ldga.h>
#include <lunaix/ds/llist.h>
#include <lunaix/types.h>
-#define PCI_CONFIG_ADDR 0xcf8
-#define PCI_CONFIG_DATA 0xcfc
-
#define PCI_TDEV 0x0
#define PCI_TPCIBRIDGE 0x1
#define PCI_TCARDBRIDGE 0x2
#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
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)去在拓扑中寻找一个设备
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,
+++ /dev/null
-#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 */
--- /dev/null
+#ifndef __LUNAIX_MC146818A_H
+#define __LUNAIX_MC146818A_H
+
+/*
+ FIXME the drivers should go into ldga
+*/
+
+#include <hal/hwrtc.h>
+
+struct hwrtc*
+mc146818a_rtc_context();
+
+#endif /* __LUNAIX_MC146818A_H */
--- /dev/null
+#ifndef __LUNAIX_BOOT_GENERIC_H
+#define __LUNAIX_BOOT_GENERIC_H
+
+#include <lunaix/types.h>
+
+// 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 */
#ifndef __LUNAIX_CLOCK_H
#define __LUNAIX_CLOCK_H
-#include <lunaix/types.h>
-
-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 <lunaix/time.h>
void
clock_init();
void
clock_walltime(datetime_t* datetime);
-int
-clock_datatime_eq(datetime_t* a, datetime_t* b);
-
/**
* @brief 返回当前系统时间,即自从开机到当前时刻的毫秒时。
*
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 */
#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
#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
#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 */
--- /dev/null
+/**
+ * @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 <lunaix/types.h>
+
+#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 */
#ifndef __LUNAIX_TWIFS_H
#define __LUNAIX_TWIFS_H
+#include <lunaix/ds/ldga.h>
#include <lunaix/fs.h>
#include <lunaix/fs/twimap.h>
#include <lunaix/spike.h>
(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();
#ifndef __LUNAIX_ISRM_H
#define __LUNAIX_ISRM_H
-#include <sys/interrupts.h>
#include <lunaix/types.h>
-
-#define IV_BASE 32
-#define IV_OS IV_BASE
-#define IV_EX 48
-#define IV_MAX 256
+#include <sys/interrupts.h>
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);
#include <lunaix/common.h>
#include <lunaix/types.h>
+#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)
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])
#define __LUNAIX_PMM_H
// Physical memory manager
-#include <lunaix/process.h>
+#include <lunaix/types.h>
#include <stddef.h>
#include <stdint.h>
// Virtual memory manager
#define VMAP_NULL 0
+
/**
* @brief 映射模式:忽略已存在映射
*
*/
#define VMAP_IGNORE 1
+
/**
* @brief 映射模式:不作实际映射。该功能用于预留出特定的地址空间
*
#ifndef __LUNAIX_PS2KBD_H
#define __LUNAIX_PS2KBD_H
-#include <hal/io.h>
#include <lunaix/ds/mutex.h>
#include <lunaix/keyboard.h>
#ifndef __LUNAIX_PROCESS_H
#define __LUNAIX_PROCESS_H
-#include <sys/interrupts.h>
#include <lunaix/clock.h>
#include <lunaix/ds/waitq.h>
#include <lunaix/fs.h>
#include <lunaix/timer.h>
#include <lunaix/types.h>
#include <stdint.h>
+#include <sys/interrupts.h>
// 虽然内核不是进程,但为了区分,这里使用Pid=-1来指代内核。这主要是方便物理页所有权检查。
#define KERNEL_PID -1
#ifndef __LUNAIX_SPIKE_H
#define __LUNAIX_SPIKE_H
+#include <lunaix/compiler.h>
+
/** Some helper functions. As helpful as Spike the Dragon! :) **/
// 除法 v/(2^k) 向上取整
: 0) \
: (31 - __builtin_clz(x)))
-#define __USER__ __attribute__((section(".usrtext")))
-
#define DO_SPIN \
while (1) \
;
#endif // __LUNAIXOS_NASSERT__
-void
+void noret
panick(const char* msg);
-void
+void noret
panickf(const char* fmt, ...);
#define wait_until(cond) \
#ifndef __LUNAIX_SYSCALL_H
#define __LUNAIX_SYSCALL_H
-#include <sys/vectors.h>
#include <usr/lunaix/syscallid.h>
#ifndef __ASM__
#define SYSCALL_ESTATUS(errno) -((errno) != 0)
-void
-syscall_install();
-
#define asmlinkage __attribute__((regparm(0)))
#define __PARAM_MAP1(t1, p1) t1 p1
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 */
--- /dev/null
+#ifndef __LUNAIX_TIME_H
+#define __LUNAIX_TIME_H
+
+#include <lunaix/types.h>
+
+#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 */
#define __LUNAIX_TIMER_H
#include <lunaix/ds/llist.h>
-#include <stdint.h>
+#include <lunaix/time.h>
+#include <sys/interrupts.h>
#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;
* @brief Desired system running frequency
*
*/
- u32_t running_frequency;
+ ticks_t running_frequency;
/**
* @brief Ticks per hertz
*
ticks_t tphz;
};
+struct timer_init_param
+{
+ struct lx_timer_context* context;
+ void* timer_update_isr;
+};
+
struct lx_timer
{
struct llist_header link;
* @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,
--- /dev/null
+#ifndef __LUNAIX_TRACE_H
+#define __LUNAIX_TRACE_H
+
+#include <lunaix/boot_generic.h>
+
+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 */
typedef unsigned long size_t;
typedef unsigned long off_t;
+typedef unsigned int cpu_t;
+
typedef u64_t lba_t;
#endif /* __LUNAIX_TYPES_H */
define ksrc_dirs
kernel
hal
- debug
libs
arch/$(ARCH)
endef
$(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
-#include <hal/ahci/hba.h>
#include <klibc/stdio.h>
#include <klibc/string.h>
+
+#include <hal/ahci/hba.h>
+
#include <lib/crc.h>
+
+#include <lunaix/blkpart_gpt.h>
#include <lunaix/block.h>
#include <lunaix/fs/twifs.h>
#include <lunaix/mm/cake.h>
+#include <lunaix/mm/page.h>
#include <lunaix/mm/valloc.h>
-#include <lunaix/syslog.h>
-
-#include <lunaix/blkpart_gpt.h>
-
#include <lunaix/spike.h>
+#include <lunaix/syslog.h>
#define BLOCK_EREAD 1
#define BLOCK_ESIG 2
--- /dev/null
+#include <klibc/string.h>
+#include <lunaix/boot_generic.h>
+#include <lunaix/mm/page.h>
+#include <lunaix/mm/pmm.h>
+#include <lunaix/mm/vmm.h>
+#include <lunaix/spike.h>
+#include <sys/mm/mempart.h>
+
+/**
+ * @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
* SOFTWARE.
*/
-#include <hal/io.h>
#include <klibc/string.h>
#include <lunaix/peripheral/serial.h>
#include <sdbg/gdbstub.h>
+#include <sys/port_io.h>
/*****************************************************************************
* Types
/*****************************************************************************
* 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)
#include <hal/acpi/acpi.h>
-#include <hal/ioapic.h>
+#include <hal/intc.h>
#include <klibc/stdio.h>
#include <lunaix/isrm.h>
#include <lunaix/lxconsole.h>
--- /dev/null
+#include <lunaix/mm/mmio.h>
+#include <lunaix/mm/page.h>
+#include <lunaix/spike.h>
+#include <lunaix/trace.h>
+
+#include <klibc/string.h>
+
+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
#include <lunaix/device.h>
+#include <lunaix/mm/page.h>
int
__null_wr_pg(struct device* dev, void* buf, size_t offset)
#include <hal/rnd.h>
#include <lunaix/device.h>
+#include <lunaix/mm/page.h>
#include <lunaix/syslog.h>
LOG_MODULE("rand")
#include <lunaix/clock.h>
#include <lunaix/input.h>
+#include <lunaix/mm/page.h>
#include <lunaix/mm/valloc.h>
#include <lunaix/spike.h>
#include <lunaix/status.h>
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
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,
+#include <lunaix/block.h>
+#include <lunaix/boot_generic.h>
#include <lunaix/common.h>
#include <lunaix/device.h>
#include <lunaix/foptions.h>
+#include <lunaix/fs/twifs.h>
#include <lunaix/input.h>
-#include <lunaix/isrm.h>
#include <lunaix/lxconsole.h>
#include <lunaix/mm/cake.h>
#include <lunaix/mm/mmio.h>
#include <lunaix/process.h>
#include <lunaix/sched.h>
#include <lunaix/spike.h>
-#include <lunaix/syscall.h>
+#include <lunaix/trace.h>
#include <lunaix/tty/tty.h>
#include <lunaix/types.h>
+#include <hal/acpi/acpi.h>
+#include <hal/intc.h>
+#include <hal/pci.h>
+
#include <sys/abi.h>
-#include <sys/boot/multiboot.h>
#include <sys/interrupts.h>
+#include <sys/mm/mempart.h>
#include <klibc/stdio.h>
#include <klibc/string.h>
-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 */
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);
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();
}
// 由于时钟中断与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();
}
{
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
#include <lunaix/mm/pmm.h>
#include <lunaix/mm/vmm.h>
+#include <sys/mm/mempart.h>
+
ptr_t
vmm_dup_page(pid_t pid, ptr_t pa)
{
#include <lunaix/syscall.h>
#include <lunaix/syscall_utils.h>
+#include <sys/mm/mempart.h>
+
// 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)
return ENOMEM;
found:
- if (found_loc >= KERNEL_MM_BASE || found_loc < USER_START) {
+ if (found_loc >= KERNEL_EXEC || found_loc < USER_START) {
return ENOMEM;
}
}
}
}
- if (!good_page_found) {
- __current->k_status = LXOUTOFMEM;
- }
return good_page_found;
}
#include <lunaix/mm/vmm.h>
#include <lunaix/spike.h>
-#define VMAP_START PG_MOUNT_BASE + MEM_4MB
-#define VMAP_END VMS_SELF
+#include <sys/mm/mempart.h>
-static ptr_t start = VMAP_START;
+static ptr_t start = VMAP;
void*
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;
}
}
-#include <hal/acpi/acpi.h>
-#include <hal/ioapic.h>
#include <lunaix/clock.h>
#include <lunaix/common.h>
#include <lunaix/input.h>
#include <lunaix/syslog.h>
#include <lunaix/timer.h>
-#include <sys/interrupts.h>
#include <hal/cpu.h>
+#include <hal/intc.h>
+
#include <klibc/string.h>
-#include <stdint.h>
+#include <sys/interrupts.h>
+#include <sys/port_io.h>
#define PS2_DEV_CMD_MAX_ATTEMPTS 5
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;
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);
{
// 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;
/*
// 等待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
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);
}
}
// 等待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
#include <hal/cpu.h>
-#include <hal/io.h>
#include <lunaix/peripheral/serial.h>
#include <lunaix/syslog.h>
+#include <sys/port_io.h>
LOG_MODULE("UART")
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);
}
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
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
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
#include <lunaix/block.h>
+#include <lunaix/boot_generic.h>
#include <lunaix/common.h>
#include <lunaix/exec.h>
#include <lunaix/foptions.h>
#include <hal/acpi/acpi.h>
#include <hal/ahci/ahci.h>
-#include <hal/apic.h>
-#include <hal/ioapic.h>
#include <hal/pci.h>
-#include <hal/rtc.h>
-
-#include <sys/boot/multiboot.h>
#include <klibc/string.h>
void
init_platform();
-void
-lock_reserved_memory();
-
-void
-unlock_reserved_memory();
-
-void
-__do_reserved_memory(int unlock);
-
int
mount_bootmedium()
{
void
__proc0()
{
+ /*
+ * We must defer boot code/data cleaning after we successfully escape that
+ * area
+ */
+ boot_cleanup();
+
init_platform();
init_proc_user_space(__current);
}
}
-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()
{
__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
#include <lunaix/status.h>
#include <lunaix/syscall.h>
#include <lunaix/syslog.h>
+
#include <sys/abi.h>
+#include <sys/mm/mempart.h>
LOG_MODULE("PROC")
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++) {
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;
return pcb->pid;
}
-extern void __kernel_end;
+extern void __kexec_end;
void
copy_kernel_stack(struct proc_info* proc, ptr_t usedMnt)
#include <sys/abi.h>
#include <sys/interrupts.h>
+#include <sys/mm/mempart.h>
-#include <hal/apic.h>
#include <hal/cpu.h>
+#include <hal/intc.h>
#include <lunaix/fs/taskfs.h>
#include <lunaix/mm/cake.h>
{
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
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;
-#include <sys/interrupts.h>
#include <klibc/stdio.h>
#include <lunaix/spike.h>
+#include <sys/interrupts.h>
static char buffer[1024];
DO_SPIN // never reach
}
-void
+void noret
panick(const char* msg)
-{
+{
cpu_trap_panic(msg);
DO_SPIN
}
+++ /dev/null
-#include <sys/interrupts.h>
-#include <lunaix/isrm.h>
-#include <lunaix/process.h>
-#include <lunaix/sched.h>
-#include <lunaix/syscall.h>
-#include <lunaix/syslog.h>
-
-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
-#include <hal/rtc.h>
+#include <hal/hwrtc.h>
+#include <hal/hwtimer.h>
#include <lunaix/clock.h>
#include <lunaix/fs/twifs.h>
#include <lunaix/spike.h>
-#include <lunaix/timer.h>
#include <klibc/string.h>
-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
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
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
*
*/
#include <sys/interrupts.h>
-#include <hal/apic.h>
-#include <hal/rtc.h>
-#include <lunaix/isrm.h>
#include <lunaix/mm/cake.h>
#include <lunaix/mm/valloc.h>
#include <lunaix/sched.h>
#include <lunaix/syslog.h>
#include <lunaix/timer.h>
-#include <hal/acpi/acpi.h>
-
-#define LVT_ENTRY_TIMER(vector, mode) (LVT_DELIVERY_FIXED | mode | vector)
+#include <hal/hwtimer.h>
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()
{
}
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;
}
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*
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*
}
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;
}
}
-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()
{
-#include <hal/io.h>
#include <klibc/string.h>
#include <lunaix/common.h>
#include <lunaix/spike.h>
#include <lunaix/tty/tty.h>
#include <stdint.h>
+#include <sys/port_io.h>
+
vga_attribute* tty_vga_buffer;
vga_attribute tty_theme_color = VGA_COLOR_BLACK;
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
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
. = 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 ) {
*(.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
@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 $@))
$(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
@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)
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 \
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):
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:
return start_addr
def expand(self, param={}):
+ super().expand(param)
+
g = self.__g.expand(param)
param["granule"] = g
--- /dev/null
+import subprocess
+import math
+import re
+
+sym_line = re.compile(r"^(?P<addr>[0-9a-f]+)\s[a-z]\s+F\s+\.[a-z._]+\s+[0-9a-f]+(?P<label>.+)$")
+
+def main(kbin, sym_out, endianness='little', bits=32):
+ assert bits >= 32
+ assert (1 << int(math.log2(bits))) == bits
+
+ b_len = bits // 8
+ result = subprocess.run(["objdump", "--syms", kbin],stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ if result.returncode != 0:
+ print(result.stderr)
+ return
+
+ def to_native(val: int):
+ return val.to_bytes(b_len, endianness, signed=False)
+
+ output = result.stdout.split(b'\n')
+ functions = []
+ for l in output:
+ l = l.decode("ascii")
+ if not l:
+ continue
+
+ mo = sym_line.match(l)
+ if not mo:
+ continue
+
+ mg = mo.groupdict()
+ addr = int(mg["addr"], 16)
+ label = mg["label"].strip() + '\0'
+
+ functions.append((addr, label))
+
+ functions = sorted(functions, key=lambda x: x[0])
+
+ # struct {
+ # ptr_t addr;
+ # unsigned int label_off;
+ # }
+ sym_struct_sz = b_len * 2
+ meta_struct_sz = 4 * 2
+ label_off_base = sym_struct_sz * len(functions) + meta_struct_sz
+ alignment = bytearray([b'\0' for _ in range(b_len - 4)])
+
+ label_off = 0
+ bmask = b_len - 1
+ text_region = bytearray()
+ null = bytearray(b'\0')
+ with open(sym_out, mode='wb') as f:
+ # struct {
+ # unsigned int num_entry;
+ # unsigned int label_off_base;
+ # }
+ f.write(to_native(len(functions)))
+ f.write(to_native(label_off_base))
+
+ for a, l in functions:
+ f.write(to_native(a))
+ f.write(to_native(label_off))
+ f.write(alignment)
+
+ text_region += bytes(l, 'ascii')
+ aligned_len = (len(l) + bmask) & ~bmask
+ for i in range(aligned_len - len(l)):
+ text_region.append(null[0])
+
+ label_off += aligned_len
+
+ f.write(text_region)
+
+import argparse
+import sys
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser()
+ parser.add_argument('elf_exec')
+ parser.add_argument('-o', '--outfile', required=True)
+ parser.add_argument('--bits', default=32)
+ parser.add_argument('--order', default='little')
+
+ args = parser.parse_args()
+
+ main(args.elf_exec, args.outfile, endianness=args.order, bits=int(args.bits))
+
},
"sys_mmap": {
"$type": "memory_map",
+ "@define": {
+ "page_mnts": 4,
+ "vms_mnts": 1
+ },
+
"width": 32,
"granule": {
"page": "0x1000",
{
"name": "kernel_exec",
"start": "3@1G",
- "size": "16@4M"
+ "size": "16@4M",
+ "block": "1@page"
},
{
- "name": "pd_mount",
- "size": "1@4M"
+ "$type": "list",
+ "$range": "[1..*vms_mnts]",
+ "name": "vms_mount_{index}",
+ "size": "1@4M",
+ "block": "1@huge"
},
{
"$type": "list",
- "$range": "[1..4]",
+ "$range": "[1..*page_mnts]",
"size": "1@page",
"name": "pg_mount_{index}"
},
{
"name": "pd_ref",
"start": "1023@4M",
- "size": "1@4M"
+ "size": "1@4M",
+ "block": "1@huge"
}
]
}
/* Generated from {{ data["template"] }}. Do NOT modify */
-#include "i386_intr.h"
#include <lunaix/types.h>
+#include <sys/i386_intr.h>
#define IDT_INTERRUPT 0x70
#define KERNEL_CS 0x8
+#ifndef __LUNAIX_MEMPART_H
+#define __LUNAIX_MEMPART_H
/* Physical Adress Space Partition */
/* Generated from {{ data["template"] }}. Do NOT modify */
#define {{ region["name"].upper() }}_END {{ hex((region["start"] + region["size"] - 1)) }}UL
{% endif %}
-{% endfor %}
\ No newline at end of file
+{% endfor %}
+#endif
\ No newline at end of file
--- /dev/null
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+struct ksyms_meta
+{
+ unsigned int entries;
+ unsigned int label_off_base;
+};
+
+struct ksyms_entry
+{
+ unsigned int addr;
+ unsigned int off;
+};
+
+void
+main()
+{
+ int fd = open("ksyms", O_RDONLY);
+ void* data = mmap(0, 0x6000, PROT_READ, MAP_PRIVATE, fd, 0);
+
+ printf("mapped at: %p\n", data);
+
+ if (data == 0) {
+ printf("unable to map, %d", errno);
+ return;
+ }
+
+ close(fd);
+
+ struct ksyms_meta* meta = (struct ksyms_meta*)data;
+
+ printf(
+ "entires: %d, label_base: %p\n", meta->entries, meta->label_off_base);
+
+ struct ksyms_entry* entries = (struct ksyms_entry*)(meta + 1);
+ for (int i = 0; i < meta->entries; i++) {
+ struct ksyms_entry* entry = &entries[i];
+ printf(
+ "addr: %p, off: %p, label: %s\n",
+ entry->addr,
+ entry->off,
+ (char*)((unsigned long)data + meta->label_off_base + entry->off));
+ }
+}