From 9a7a9c079d0ab0366673beff73ffa710fe3b76c8 Mon Sep 17 00:00:00 2001 From: Minep Date: Sat, 22 Oct 2022 01:13:59 +0100 Subject: [PATCH] refactor: isrm to centeralize interrupt/irq resources management. --- lunaix-os/debug/sdbg.c | 14 +--- lunaix-os/hal/acpi/acpi.c | 10 +++ lunaix-os/hal/ahci/ahci.c | 4 +- lunaix-os/hal/ioapic.c | 28 ------- lunaix-os/includes/arch/x86/interrupts.h | 10 --- lunaix-os/includes/hal/acpi/acpi.h | 3 + lunaix-os/includes/lunaix/isrm.h | 45 ++++++++++ lunaix-os/includes/lunaix/spike.h | 2 +- lunaix-os/kernel/asm/x86/i386_isrm.c | 101 +++++++++++++++++++++++ lunaix-os/kernel/asm/x86/interrupts.c | 43 ++-------- lunaix-os/kernel/asm/x86/intr_routines.c | 20 ++--- lunaix-os/kernel/k_init.c | 10 +++ lunaix-os/kernel/peripheral/ps2kbd.c | 7 +- lunaix-os/kernel/proc0.c | 22 +++-- lunaix-os/kernel/syscall.c | 3 +- lunaix-os/kernel/time/timer.c | 28 +++++-- 16 files changed, 232 insertions(+), 118 deletions(-) create mode 100644 lunaix-os/includes/lunaix/isrm.h create mode 100644 lunaix-os/kernel/asm/x86/i386_isrm.c diff --git a/lunaix-os/debug/sdbg.c b/lunaix-os/debug/sdbg.c index 2309ece..3cc23cf 100644 --- a/lunaix-os/debug/sdbg.c +++ b/lunaix-os/debug/sdbg.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -99,18 +100,11 @@ sdbg_imm(const isr_param* param) while (1) ; } - -extern uint8_t -ioapic_get_irq(acpi_context* acpi_ctx, uint8_t old_irq); - void sdbg_init() { - intr_subscribe(UART_COM1, sdbg_loop); - intr_subscribe(INSTR_DEBUG, sdbg_loop); // #DB - intr_subscribe(INSTR_BREAK, sdbg_loop); // #BRK + isrm_bindiv(INSTR_DEBUG, sdbg_loop); // #DB + isrm_bindiv(INSTR_BREAK, sdbg_loop); // #BRK - acpi_context* acpi_ctx = acpi_get_context(); - uint8_t irq = ioapic_get_irq(acpi_ctx, COM1_IRQ); - ioapic_redirect(irq, UART_COM1, 0, IOAPIC_DELMOD_FIXED); + isrm_bindirq(COM1_IRQ, sdbg_loop); } \ No newline at end of file diff --git a/lunaix-os/hal/acpi/acpi.c b/lunaix-os/hal/acpi/acpi.c index c6a566e..3f8a25f 100644 --- a/lunaix-os/hal/acpi/acpi.c +++ b/lunaix-os/hal/acpi/acpi.c @@ -76,6 +76,16 @@ acpi_rsdp_validate(acpi_rsdp_t* rsdp) return sum == 0; } +uint8_t +acpi_gistranslate(uint8_t old_irq) +{ + if (old_irq >= 24) { + return old_irq; + } + acpi_intso_t* int_override = ctx->madt.irq_exception[old_irq]; + return int_override ? (uint8_t)int_override->gsi : old_irq; +} + #define VIRTUAL_BOX_PROBLEM acpi_rsdp_t* diff --git a/lunaix-os/hal/ahci/ahci.c b/lunaix-os/hal/ahci/ahci.c index 43b8f1e..74ba928 100644 --- a/lunaix-os/hal/ahci/ahci.c +++ b/lunaix-os/hal/ahci/ahci.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -88,8 +89,7 @@ ahci_init() pci_write_cspace(ahci_dev->cspace_base, PCI_REG_STATUS_CMD, cmd); - pci_setup_msi(ahci_dev, AHCI_HBA_IV); - intr_subscribe(AHCI_HBA_IV, __ahci_hba_isr); + pci_setup_msi(ahci_dev, isrm_ivexalloc(__ahci_hba_isr)); memset(&hba, 0, sizeof(hba)); diff --git a/lunaix-os/hal/ioapic.c b/lunaix-os/hal/ioapic.c index 5a03eff..edd374f 100644 --- a/lunaix-os/hal/ioapic.c +++ b/lunaix-os/hal/ioapic.c @@ -9,9 +9,6 @@ static volatile uintptr_t _ioapic_base; -uint8_t -ioapic_get_irq(acpi_context* acpi_ctx, uint8_t old_irq); - void ioapic_init() { @@ -20,31 +17,6 @@ ioapic_init() acpi_context* acpi_ctx = acpi_get_context(); _ioapic_base = ioremap(acpi_ctx->madt.ioapic->ioapic_addr & ~0xfff, 4096); - - // 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. - - // The ioapic_get_irq is to make sure we capture those overriden IRQs - - // grab ourselves these irq numbers - uint8_t irq_rtc = ioapic_get_irq(acpi_ctx, PC_AT_IRQ_RTC); - - // PC_AT_IRQ_RTC -> RTC_TIMER_IV, fixed, edge trigged, polarity=high, - // physical, APIC ID 0 - ioapic_redirect(irq_rtc, RTC_TIMER_IV, 0, IOAPIC_DELMOD_FIXED); -} - -uint8_t -ioapic_get_irq(acpi_context* acpi_ctx, uint8_t old_irq) -{ - if (old_irq >= 24) { - return old_irq; - } - acpi_intso_t* int_override = acpi_ctx->madt.irq_exception[old_irq]; - return int_override ? (uint8_t)int_override->gsi : old_irq; } void diff --git a/lunaix-os/includes/arch/x86/interrupts.h b/lunaix-os/includes/arch/x86/interrupts.h index 70e7149..822b99d 100644 --- a/lunaix-os/includes/arch/x86/interrupts.h +++ b/lunaix-os/includes/arch/x86/interrupts.h @@ -32,16 +32,6 @@ typedef struct unsigned int ss; } __attribute__((packed)) isr_param; -typedef void (*int_subscriber)(const isr_param*); - -void -intr_subscribe(const uint8_t vector, int_subscriber); - -void -intr_unsubscribe(const uint8_t vector, int_subscriber); - -void intr_set_fallback_handler(int_subscriber); - void intr_handler(isr_param* param); diff --git a/lunaix-os/includes/hal/acpi/acpi.h b/lunaix-os/includes/hal/acpi/acpi.h index 2e788d2..46713b8 100644 --- a/lunaix-os/includes/hal/acpi/acpi.h +++ b/lunaix-os/includes/hal/acpi/acpi.h @@ -56,4 +56,7 @@ acpi_init(multiboot_info_t* mb_info); acpi_context* acpi_get_context(); +uint8_t +acpi_gistranslate(uint8_t old_irq); + #endif /* __LUNAIX_ACPI_ACPI_H */ diff --git a/lunaix-os/includes/lunaix/isrm.h b/lunaix-os/includes/lunaix/isrm.h new file mode 100644 index 0000000..32ba31d --- /dev/null +++ b/lunaix-os/includes/lunaix/isrm.h @@ -0,0 +1,45 @@ +/** + * @file irqm.h + * @author Lunaixsky + * @brief ISR Manager, managing the interrupt service routine allocations + * @version 0.1 + * @date 2022-10-18 + * + * @copyright Copyright (c) 2022 + * + */ +#ifndef __LUNAIX_ISRM_H +#define __LUNAIX_ISRM_H + +#include +#include + +#define IV_BASE 32 +#define IV_OS IV_BASE +#define IV_EX 48 +#define IV_MAX 256 + +typedef void (*isr_cb)(const isr_param*); + +void +isrm_init(); + +void +isrm_ivfree(uint32_t iv); + +uint32_t +isrm_ivosalloc(isr_cb handler); + +uint32_t +isrm_ivexalloc(isr_cb handler); + +uint32_t +isrm_bindirq(uint32_t irq, isr_cb irq_handler); + +uint32_t +isrm_bindiv(uint32_t iv, isr_cb handler); + +isr_cb +isrm_get(uint32_t iv); + +#endif /* __LUNAIX_ISRM_H */ diff --git a/lunaix-os/includes/lunaix/spike.h b/lunaix-os/includes/lunaix/spike.h index 274bcf6..d9c234d 100644 --- a/lunaix-os/includes/lunaix/spike.h +++ b/lunaix-os/includes/lunaix/spike.h @@ -14,7 +14,7 @@ // 获取v最近的最大k倍数 #define ROUNDUP(v, k) (((v) + (k)-1) & ~((k)-1)) -// 获取v最近的最小k倍数 +// 获取v最近的最小k倍数 (k=2^m) #define ROUNDDOWN(v, k) ((v) & ~((k)-1)) #define MIN(a, b) ((a) < (b) ? (a) : (b)) diff --git a/lunaix-os/kernel/asm/x86/i386_isrm.c b/lunaix-os/kernel/asm/x86/i386_isrm.c new file mode 100644 index 0000000..0a26c3b --- /dev/null +++ b/lunaix-os/kernel/asm/x86/i386_isrm.c @@ -0,0 +1,101 @@ +#include +#include + +#include +#include + +/* + total: 256 ivs + 0~31: reserved for sys use (x32) + 32~47: reserved for os use (x16) + 48~ : free to allocate for external hardware use. (x208) +*/ + +static char iv_bmp[(IV_MAX - IV_BASE) / 8]; +static isr_cb handlers[IV_MAX]; + +extern void +intr_routine_fallback(const isr_param* param); + +void +isrm_init() +{ + for (size_t i = 0; i < 256; i++) { + handlers[i] = intr_routine_fallback; + } +} + +static inline uint32_t +__ivalloc_within(size_t a, size_t b, isr_cb handler) +{ + a = (a - IV_BASE) / 8; + b = (b - IV_BASE) / 8; + for (size_t i = a; i < b; i++) { + char chunk = iv_bmp[i], j = 0; + if (chunk == 0xff) + continue; + while ((chunk & 0x1)) { + chunk >>= 1; + j++; + } + iv_bmp[i] |= 1 << j; + uint32_t iv = IV_BASE + i * 8 + j; + handlers[iv] = handler ? handler : intr_routine_fallback; + return iv; + } + return 0; +} + +uint32_t +isrm_ivosalloc(isr_cb handler) +{ + return __ivalloc_within(IV_BASE, IV_EX, handler); +} + +uint32_t +isrm_ivexalloc(isr_cb handler) +{ + return __ivalloc_within(IV_EX, IV_MAX, handler); +} + +void +isrm_ivfree(uint32_t iv) +{ + assert(iv < 256); + if (iv >= IV_BASE) { + iv_bmp[(iv - IV_BASE) / 8] &= ~(1 << ((iv - IV_BASE) % 8)); + } + handlers[iv] = intr_routine_fallback; +} + +uint32_t +isrm_bindirq(uint32_t irq, isr_cb irq_handler) +{ + uint32_t iv; + if (!(iv = isrm_ivexalloc(irq_handler))) { + panickf("out of IV resource. (irq=%d)", irq); + 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); + return iv; +} + +uint32_t +isrm_bindiv(uint32_t iv, isr_cb handler) +{ + assert(iv < 256); + if (iv >= IV_BASE) { + iv_bmp[(iv - IV_BASE) / 8] |= 1 << ((iv - IV_BASE) % 8); + } + handlers[iv] = handler; +} + +isr_cb +isrm_get(uint32_t iv) +{ + assert(iv < 256); + return handlers[iv]; +} \ No newline at end of file diff --git a/lunaix-os/kernel/asm/x86/interrupts.c b/lunaix-os/kernel/asm/x86/interrupts.c index 864c7da..25b3791 100644 --- a/lunaix-os/kernel/asm/x86/interrupts.c +++ b/lunaix-os/kernel/asm/x86/interrupts.c @@ -1,7 +1,10 @@ #include #include + #include #include + +#include #include #include #include @@ -9,31 +12,7 @@ #include #include -LOG_MODULE("intr") - -static int_subscriber subscribers[256]; - -static int_subscriber fallback = (int_subscriber)0; - -void -intr_subscribe(const uint8_t vector, int_subscriber subscriber) -{ - subscribers[vector] = subscriber; -} - -void -intr_unsubscribe(const uint8_t vector, int_subscriber subscriber) -{ - if (subscribers[vector] == subscriber) { - subscribers[vector] = (int_subscriber)0; - } -} - -void -intr_set_fallback_handler(int_subscriber subscribers) -{ - fallback = subscribers; -} +LOG_MODULE("INTR") extern x86_page_table* __kernel_ptd; @@ -45,15 +24,8 @@ intr_handler(isr_param* param) isr_param* lparam = &__current->intr_ctx; if (lparam->vector <= 255) { - int_subscriber subscriber = subscribers[lparam->vector]; - if (subscriber) { - subscriber(param); - goto done; - } - } - - if (fallback) { - fallback(lparam); + isr_cb subscriber = isrm_get(lparam->vector); + subscriber(param); goto done; } @@ -66,8 +38,7 @@ intr_handler(isr_param* param) 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 (lparam->vector >= EX_INTERRUPT_BEGIN && - lparam->vector != APIC_SPIV_IV) { + if (lparam->vector >= IV_EX && lparam->vector != APIC_SPIV_IV) { apic_done_servicing(); } diff --git a/lunaix-os/kernel/asm/x86/intr_routines.c b/lunaix-os/kernel/asm/x86/intr_routines.c index 402ceea..285356f 100644 --- a/lunaix-os/kernel/asm/x86/intr_routines.c +++ b/lunaix-os/kernel/asm/x86/intr_routines.c @@ -1,4 +1,6 @@ #include + +#include #include #include #include @@ -94,16 +96,14 @@ intr_routine_sched(const isr_param* param) void intr_routine_init() { - intr_subscribe(FAULT_DIVISION_ERROR, intr_routine_divide_zero); - intr_subscribe(FAULT_GENERAL_PROTECTION, intr_routine_general_protection); - intr_subscribe(FAULT_PAGE_FAULT, intr_routine_page_fault); - intr_subscribe(FAULT_STACK_SEG_FAULT, intr_routine_page_fault); - - intr_subscribe(LUNAIX_SYS_PANIC, intr_routine_sys_panic); - intr_subscribe(LUNAIX_SCHED, intr_routine_sched); + isrm_bindiv(FAULT_DIVISION_ERROR, intr_routine_divide_zero); + isrm_bindiv(FAULT_GENERAL_PROTECTION, intr_routine_general_protection); + isrm_bindiv(FAULT_PAGE_FAULT, intr_routine_page_fault); + isrm_bindiv(FAULT_STACK_SEG_FAULT, intr_routine_page_fault); - intr_subscribe(APIC_SPIV_IV, intr_routine_apic_spi); - intr_subscribe(APIC_ERROR_IV, intr_routine_apic_error); + isrm_bindiv(LUNAIX_SYS_PANIC, intr_routine_sys_panic); + isrm_bindiv(LUNAIX_SCHED, intr_routine_sched); - intr_set_fallback_handler(intr_routine_fallback); + isrm_bindiv(APIC_SPIV_IV, intr_routine_apic_spi); + isrm_bindiv(APIC_ERROR_IV, intr_routine_apic_error); } \ No newline at end of file diff --git a/lunaix-os/kernel/k_init.c b/lunaix-os/kernel/k_init.c index ce4ac6a..32164c8 100644 --- a/lunaix-os/kernel/k_init.c +++ b/lunaix-os/kernel/k_init.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -46,9 +47,12 @@ setup_memory(multiboot_memory_map_t* map, size_t map_size); void _kernel_pre_init() { + // interrupts _init_idt(); + isrm_init(); intr_routine_init(); + // memory pmm_init(MEM_1MB + (_k_init_mb_info->mem_upper << 10)); vmm_init(); @@ -68,12 +72,16 @@ void _kernel_init() { int errno = 0; + + // allocators cake_init(); valloc_init(); + // crt tty_init(ioremap(VGA_FRAMEBUFFER, PG_SIZE)); tty_set_theme(VGA_COLOR_WHITE, VGA_COLOR_BLACK); + // file system & device subsys vfs_init(); fsm_init(); input_init(); @@ -92,6 +100,8 @@ _kernel_init() sched_init(); + syscall_install(); + spawn_proc0(); } diff --git a/lunaix-os/kernel/peripheral/ps2kbd.c b/lunaix-os/kernel/peripheral/ps2kbd.c index df6ffc1..fbd7e75 100644 --- a/lunaix-os/kernel/peripheral/ps2kbd.c +++ b/lunaix-os/kernel/peripheral/ps2kbd.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -188,9 +189,6 @@ ps2_kbd_init() // 至此,PS/2控制器和设备已完成初始化,可以正常使用。 - // 将我们的键盘驱动挂载到第204号中断上(已由IOAPIC映射至IRQ#1), - intr_subscribe(PC_KBD_IV, intr_ps2_kbd_handler); - // 搞一个计时器,将我们的 ps2_process_cmd // 挂上去。每隔5毫秒执行排在队头的命令。 // 为什么只执行队头的命令,而不是全部的命令? @@ -207,8 +205,7 @@ ps2_kbd_init() * * 所以,保险的方法是:在初始化后才去设置ioapic,这样一来我们就能有一个稳定的IRQ#1以放心使用。 */ - uint8_t irq_kbd = ioapic_get_irq(acpi_ctx, PC_AT_IRQ_KBD); - ioapic_redirect(irq_kbd, PC_KBD_IV, 0, IOAPIC_DELMOD_FIXED); + isrm_bindirq(PC_AT_IRQ_KBD, intr_ps2_kbd_handler); done: cpu_enable_interrupt(); diff --git a/lunaix-os/kernel/proc0.c b/lunaix-os/kernel/proc0.c index 2a41032..14e4862 100644 --- a/lunaix-os/kernel/proc0.c +++ b/lunaix-os/kernel/proc0.c @@ -86,9 +86,6 @@ __proc0_usr() int fdstdin = dup2(stdout, 1); pid_t p; - // if (!fork()) { - // _pconsole_main(); - // } if (!(p = fork())) { #ifndef USE_DEMO @@ -132,6 +129,7 @@ __proc0() init_proc_user_space(__current); + // user space asm volatile("movw %0, %%ax\n" "movw %%ax, %%es\n" "movw %%ax, %%ds\n" @@ -159,32 +157,44 @@ init_platform() // 锁定所有系统预留页(内存映射IO,ACPI之类的),并且进行1:1映射 lock_reserved_memory(); - rtc_init(); + // firmware acpi_init(_k_init_mb_info); + + // die apic_init(); ioapic_init(); + + // debugger serial_init(); sdbg_init(); + + // timers & clock + rtc_init(); timer_init(SYS_TIMER_FREQUENCY_HZ); clock_init(); + + // peripherals & chipset features ps2_kbd_init(); pci_init(); block_init(); ahci_init(); - syscall_install(); - + // 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 < (uintptr_t)(&__init_hhk_end); i += PG_SIZE) { vmm_del_mapping(PD_REFERENCED, (void*)i); pmm_free_page(KERNEL_PID, (void*)i); } + // reserve higher half for (size_t i = L1_INDEX(KERNEL_MM_BASE); i < 1023; i++) { vmm_set_mapping(PD_REFERENCED, i << 22, 0, 0, VMAP_NOMAP); } diff --git a/lunaix-os/kernel/syscall.c b/lunaix-os/kernel/syscall.c index 5cee205..6f0a2ba 100644 --- a/lunaix-os/kernel/syscall.c +++ b/lunaix-os/kernel/syscall.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -12,5 +13,5 @@ syscall_hndlr(const isr_param* param); void syscall_install() { - intr_subscribe(LUNAIX_SYS_CALL, syscall_hndlr); + isrm_bindiv(LUNAIX_SYS_CALL, syscall_hndlr); } \ No newline at end of file diff --git a/lunaix-os/kernel/time/timer.c b/lunaix-os/kernel/time/timer.c index 7d9a391..bf99328 100644 --- a/lunaix-os/kernel/time/timer.c +++ b/lunaix-os/kernel/time/timer.c @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -20,6 +21,8 @@ #include #include +#include + #define LVT_ENTRY_TIMER(vector, mode) (LVT_DELIVERY_FIXED | mode | vector) LOG_MODULE("TIMER"); @@ -69,10 +72,20 @@ timer_init(uint32_t frequency) // 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 + uint32_t iv_rtc = isrm_bindirq(PC_AT_IRQ_RTC, temp_intr_routine_rtc_tick); + uint32_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(APIC_TIMER_IV, LVT_TIMER_ONESHOT)); + LVT_ENTRY_TIMER(iv_timer, LVT_TIMER_ONESHOT)); // Set divider to 64 apic_write_reg(APIC_TIMER_DCR, APIC_TIMER_DIV64); @@ -110,9 +123,6 @@ timer_init(uint32_t frequency) rtc_counter = 0; apic_timer_done = 0; - intr_subscribe(APIC_TIMER_IV, temp_intr_routine_apic_timer); - intr_subscribe(RTC_TIMER_IV, temp_intr_routine_rtc_tick); - rtc_enable_timer(); // start RTC timer apic_write_reg(APIC_TIMER_ICR, APIC_CALIBRATION_CONST); // start APIC timer @@ -129,12 +139,12 @@ timer_init(uint32_t frequency) timer_ctx->tphz = timer_ctx->base_frequency / frequency; // cleanup - intr_unsubscribe(APIC_TIMER_IV, temp_intr_routine_apic_timer); - intr_unsubscribe(RTC_TIMER_IV, temp_intr_routine_rtc_tick); + isrm_ivfree(iv_timer); + isrm_ivfree(iv_rtc); - apic_write_reg(APIC_TIMER_LVT, - LVT_ENTRY_TIMER(APIC_TIMER_IV, LVT_TIMER_PERIODIC)); - intr_subscribe(APIC_TIMER_IV, timer_update); + 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); -- 2.27.0