diff --git a/.vscode/settings.json b/.vscode/settings.json index 04886d30..c1a9f417 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,14 +10,12 @@ "glib.h": "c", "asm.h": "c", "memory.h": "c", - "irq.h": "c", "multiboot2.h": "c", "kprint.h": "c", "8259a.h": "c", "ptrace.h": "c", "mouse.h": "c", "keyboard.h": "c", - "apic.h": "c", "ps2_keyboard.h": "c", "algorithm": "c", "array": "c", @@ -27,7 +25,6 @@ "cassert": "c", "cctype": "c", "cerrno": "c", - "cfloat": "c", "chrono": "c", "climits": "c", "clocale": "c", @@ -83,7 +80,6 @@ "cinttypes": "c", "cstdbool": "c", "typeinfo": "c", - "x86_64_ipi.h": "c", "unistd.h": "c", "syscall_num.h": "c", "stdint.h": "c", @@ -92,7 +88,6 @@ "types.h": "c", "string.h": "c", "math.h": "c", - "ipi.h": "c", "arch.h": "c", "stdio.h": "c", "wait_queue.h": "c", @@ -109,10 +104,8 @@ "ia64_msi.h": "c", "errno.h": "c", "bug.h": "c", - "apic_timer.h": "c", "sched.h": "c", "preempt.h": "c", - "softirq.h": "c", "screen_manager.h": "c", "textui.h": "c", "atomic.h": "c", @@ -120,7 +113,6 @@ "fat_ent.h": "c", "semaphore.h": "c", "mm-types.h": "c", - "vfs.h": "c", "current.h": "c", "traceback.h": "c", "bitcount.h": "c", diff --git a/build-scripts/kernel_build/src/cfiles/arch/x86_64.rs b/build-scripts/kernel_build/src/cfiles/arch/x86_64.rs index e10a5a89..e473a8a9 100644 --- a/build-scripts/kernel_build/src/cfiles/arch/x86_64.rs +++ b/build-scripts/kernel_build/src/cfiles/arch/x86_64.rs @@ -18,7 +18,6 @@ impl CFilesArch for X86_64CFilesArch { } fn setup_files(&self, _c: &mut Build, files: &mut Vec) { - files.push(arch_path("driver/hpet.c")); // 获取`kernel/src/arch/x86_64/driver/apic`下的所有C文件 files.append(&mut FileUtils::list_all_files( &arch_path("driver/apic"), diff --git a/docs/kernel/core_api/softirq.md b/docs/kernel/core_api/softirq.md index 8765299e..452c1f20 100644 --- a/docs/kernel/core_api/softirq.md +++ b/docs/kernel/core_api/softirq.md @@ -162,12 +162,3 @@ fn main() { } ``` -### 3.4. 为C提供的接口 - -```c -extern void rs_softirq_init(); -extern void rs_raise_softirq(uint32_t sirq_num); -extern void rs_unregister_softirq(uint32_t sirq_num); -extern void rs_do_softirq(); -extern void rs_clear_softirq_pending(uint32_t softirq_num); -``` diff --git a/kernel/crates/bitmap/src/alloc_bitmap.rs b/kernel/crates/bitmap/src/alloc_bitmap.rs index e98610bb..d4c6c510 100644 --- a/kernel/crates/bitmap/src/alloc_bitmap.rs +++ b/kernel/crates/bitmap/src/alloc_bitmap.rs @@ -2,6 +2,7 @@ use alloc::vec::Vec; use crate::{bitmap_core::BitMapCore, traits::BitMapOps}; +#[derive(Clone)] pub struct AllocBitmap { elements: usize, data: Vec, diff --git a/kernel/src/Makefile b/kernel/src/Makefile index 4fcdf595..204f63fd 100644 --- a/kernel/src/Makefile +++ b/kernel/src/Makefile @@ -36,7 +36,7 @@ export ASFLAGS := --64 LD_LIST := "" -kernel_subdirs := common driver debug exception smp syscall libs time +kernel_subdirs := common driver debug smp syscall libs time kernel_rust: diff --git a/kernel/src/arch/riscv64/cpu.rs b/kernel/src/arch/riscv64/cpu.rs index be943990..6cb996c2 100644 --- a/kernel/src/arch/riscv64/cpu.rs +++ b/kernel/src/arch/riscv64/cpu.rs @@ -1,6 +1,8 @@ +use crate::smp::cpu::ProcessorId; + /// 获取当前cpu的id #[inline] -pub fn current_cpu_id() -> u32 { +pub fn current_cpu_id() -> ProcessorId { unimplemented!("RiscV64 current_cpu_id") } diff --git a/kernel/src/arch/x86_64/acpi.rs b/kernel/src/arch/x86_64/acpi.rs index 84104d04..842f1b58 100644 --- a/kernel/src/arch/x86_64/acpi.rs +++ b/kernel/src/arch/x86_64/acpi.rs @@ -1,6 +1,6 @@ use system_error::SystemError; -use crate::{driver::acpi::acpi_manager, kinfo, mm::percpu::PerCpu}; +use crate::{driver::acpi::acpi_manager, kinfo, mm::percpu::PerCpu, smp::cpu::ProcessorId}; use super::smp::SMP_BOOT_DATA; @@ -11,16 +11,19 @@ pub(super) fn early_acpi_boot_init() -> Result<(), SystemError> { let processor_info = platform_info.processor_info.ok_or(SystemError::ENODEV)?; unsafe { - SMP_BOOT_DATA.set_phys_id(0, processor_info.boot_processor.local_apic_id as usize); - let mut cnt = 1; + SMP_BOOT_DATA.set_phys_id( + ProcessorId::new(0), + processor_info.boot_processor.local_apic_id as usize, + ); + let mut cnt = ProcessorId::new(1); for ap in processor_info.application_processors.iter() { - if cnt >= PerCpu::MAX_CPU_NUM { + if cnt.data() >= PerCpu::MAX_CPU_NUM { break; } SMP_BOOT_DATA.set_phys_id(cnt, ap.local_apic_id as usize); - cnt += 1; + cnt = ProcessorId::new(cnt.data() + 1); } - SMP_BOOT_DATA.set_cpu_count(cnt); + SMP_BOOT_DATA.set_cpu_count(cnt.data()); SMP_BOOT_DATA.mark_initialized(); } kinfo!( diff --git a/kernel/src/arch/x86_64/c_adapter.rs b/kernel/src/arch/x86_64/c_adapter.rs index 5666b303..3cffb50e 100644 --- a/kernel/src/arch/x86_64/c_adapter.rs +++ b/kernel/src/arch/x86_64/c_adapter.rs @@ -1,6 +1,6 @@ -use crate::time::TimeArch; +use crate::{sched::SchedArch, time::TimeArch}; -use super::{driver::tsc::TSCManager, syscall::init_syscall_64, CurrentTimeArch}; +use super::{driver::tsc::TSCManager, syscall::init_syscall_64, CurrentSchedArch, CurrentTimeArch}; /// 获取当前的时间戳 #[no_mangle] @@ -18,3 +18,8 @@ unsafe extern "C" fn rs_tsc_get_cpu_khz() -> u64 { pub unsafe extern "C" fn rs_init_syscall_64() { init_syscall_64(); } + +#[no_mangle] +unsafe extern "C" fn rs_init_current_core_sched() { + CurrentSchedArch::initial_setup_sched_local(); +} diff --git a/kernel/src/arch/x86_64/cpu.rs b/kernel/src/arch/x86_64/cpu.rs index 300088cf..bf3c9666 100644 --- a/kernel/src/arch/x86_64/cpu.rs +++ b/kernel/src/arch/x86_64/cpu.rs @@ -1,11 +1,13 @@ use x86::cpuid::{cpuid, CpuIdResult}; -/// @brief 获取当前cpu的apic id +use crate::smp::cpu::ProcessorId; + +/// 获取当前cpu的apic id #[inline] -pub fn current_cpu_id() -> u32 { +pub fn current_cpu_id() -> ProcessorId { let cpuid_res: CpuIdResult = cpuid!(0x1); let cpu_id = (cpuid_res.ebx >> 24) & 0xff; - return cpu_id; + return ProcessorId::new(cpu_id); } /// 重置cpu diff --git a/kernel/src/arch/x86_64/driver/apic/apic.c b/kernel/src/arch/x86_64/driver/apic/apic.c deleted file mode 100644 index fbbb3fcb..00000000 --- a/kernel/src/arch/x86_64/driver/apic/apic.c +++ /dev/null @@ -1,205 +0,0 @@ -#include "apic.h" -#include "apic_timer.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#pragma GCC push_options -#pragma GCC optimize("O0") -// 导出定义在irq.c中的中段门表 -extern void (*interrupt_table[26])(void); -extern uint32_t rs_current_pcb_preempt_count(); -extern uint32_t rs_current_pcb_pid(); -extern uint32_t rs_current_pcb_flags(); -extern void rs_apic_init_bsp(); - -extern void rs_apic_local_apic_edge_ack(uint8_t irq_num); - -extern int rs_ioapic_install(uint8_t vector, uint8_t dest, bool level_triggered, bool active_high, bool dest_logical); -extern void rs_ioapic_uninstall(uint8_t irq_num); -extern void rs_ioapic_enable(uint8_t irq_num); -extern void rs_ioapic_disable(uint8_t irq_num); - -/** - * @brief 中断服务程序 - * - * @param rsp 中断栈指针 - * @param number 中断向量号 - */ -void do_IRQ(struct pt_regs *rsp, ul number) -{ - - if ((rsp->cs & 0x3) == 3) - { - asm volatile("swapgs" ::: "memory"); - } - if (number < 0x80 && number >= 32) // 以0x80为界限,低于0x80的是外部中断控制器,高于0x80的是Local APIC - { - // ==========外部中断控制器======== - irq_desc_t *irq = &interrupt_desc[number - 32]; - - // 执行中断上半部处理程序 - if (irq != NULL && irq->handler != NULL) - irq->handler(number, irq->parameter, rsp); - else - kwarn("Intr vector [%d] does not have a handler!"); - // 向中断控制器发送应答消息 - // if (irq->controller != NULL && irq->controller->ack != NULL) - // irq->controller->ack(number); - // else - // rs_apic_local_apic_edge_ack(number); - rs_apic_local_apic_edge_ack(number); - } - else if (number >= 200) - { - rs_apic_local_apic_edge_ack(number); - - { - irq_desc_t *irq = &SMP_IPI_desc[number - 200]; - if (irq->handler != NULL) - irq->handler(number, irq->parameter, rsp); - } - } - else if (number >= 150 && number < 200) - { - irq_desc_t *irq = &local_apic_interrupt_desc[number - 150]; - - // 执行中断上半部处理程序 - if (irq != NULL && irq->handler != NULL) - irq->handler(number, irq->parameter, rsp); - else - kwarn("Intr vector [%d] does not have a handler!"); - // 向中断控制器发送应答消息 - // if (irq->controller != NULL && irq->controller->ack != NULL) - // irq->controller->ack(number); - // else - // rs_apic_local_apic_edge_ack(number); - rs_apic_local_apic_edge_ack(number); - } - else - { - - kwarn("do IRQ receive: %d", number); - // 忽略未知中断 - return; - } - - // kdebug("before softirq"); - // 进入软中断处理程序 - rs_do_softirq(); - - // kdebug("after softirq"); - // 检测当前进程是否持有自旋锁,若持有自旋锁,则不进行抢占式的进程调度 - if (rs_current_pcb_preempt_count() > 0) - { - return; - } - else if ((int32_t)rs_current_pcb_preempt_count() < 0) - kBUG("current_pcb->preempt_count<0! pid=%d", rs_current_pcb_pid()); // should not be here - - // 检测当前进程是否可被调度 - if ((rs_current_pcb_flags() & PF_NEED_SCHED) && number == APIC_TIMER_IRQ_NUM) - { - io_mfence(); - sched(); - } -} - -// =========== 中断控制操作接口 ============ -void apic_ioapic_enable(ul irq_num) -{ - rs_ioapic_enable(irq_num); -} - -void apic_ioapic_disable(ul irq_num) -{ - rs_ioapic_disable(irq_num); -} - -ul apic_ioapic_install(ul irq_num, void *arg) -{ - struct apic_IO_APIC_RTE_entry *entry = (struct apic_IO_APIC_RTE_entry *)arg; - uint8_t dest = 0; - if (entry->dest_mode) - { - dest = entry->destination.logical.logical_dest; - } - else - { - dest = entry->destination.physical.phy_dest; - } - - return rs_ioapic_install(entry->vector, dest, entry->trigger_mode, entry->polarity, entry->dest_mode); -} - -void apic_ioapic_uninstall(ul irq_num) -{ - rs_ioapic_uninstall(irq_num); -} - -void apic_ioapic_edge_ack(ul irq_num) // 边沿触发 -{ - - rs_apic_local_apic_edge_ack(irq_num); -} - -/** - * @brief local apic 边沿触发应答 - * - * @param irq_num - */ - -void apic_local_apic_edge_ack(ul irq_num) -{ - rs_apic_local_apic_edge_ack(irq_num); -} - -/** - * @brief 构造RTE Entry结构体 - * - * @param entry 返回的结构体 - * @param vector 中断向量 - * @param deliver_mode 投递模式 - * @param dest_mode 目标模式 - * @param deliver_status 投递状态 - * @param polarity 电平触发极性 - * @param irr 远程IRR标志位(只读) - * @param trigger 触发模式 - * @param mask 屏蔽标志位,(0为未屏蔽, 1为已屏蔽) - * @param dest_apicID 目标apicID - */ -void apic_make_rte_entry(struct apic_IO_APIC_RTE_entry *entry, uint8_t vector, uint8_t deliver_mode, uint8_t dest_mode, - uint8_t deliver_status, uint8_t polarity, uint8_t irr, uint8_t trigger, uint8_t mask, - uint8_t dest_apicID) -{ - - entry->vector = vector; - entry->deliver_mode = deliver_mode; - entry->dest_mode = dest_mode; - entry->deliver_status = deliver_status; - entry->polarity = polarity; - entry->remote_IRR = irr; - entry->trigger_mode = trigger; - entry->mask = mask; - - entry->reserved = 0; - - if (dest_mode == DEST_PHYSICAL) - { - entry->destination.physical.phy_dest = dest_apicID; - entry->destination.physical.reserved1 = 0; - entry->destination.physical.reserved2 = 0; - } - else - { - entry->destination.logical.logical_dest = dest_apicID; - entry->destination.logical.reserved1 = 0; - } -} - -#pragma GCC pop_options \ No newline at end of file diff --git a/kernel/src/arch/x86_64/driver/apic/apic.h b/kernel/src/arch/x86_64/driver/apic/apic.h deleted file mode 100644 index c8c483a0..00000000 --- a/kernel/src/arch/x86_64/driver/apic/apic.h +++ /dev/null @@ -1,284 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -#pragma GCC push_options -#pragma GCC optimize("O0") - -// 当前apic启用状态标志 -extern uint8_t __apic_enable_state; -#define APIC_XAPIC_ENABLED 0 -#define APIC_X2APIC_ENABLED 1 -#define CURRENT_APIC_STATE (__apic_enable_state) - -// ======== local apic 寄存器虚拟地址偏移量表 ======= -// 0x00~0x10 Reserved. -#define LOCAL_APIC_OFFSET_Local_APIC_ID 0x20 -#define LOCAL_APIC_OFFSET_Local_APIC_Version 0x30 -// 0x40~0x70 Reserved. -#define LOCAL_APIC_OFFSET_Local_APIC_TPR 0x80 -#define LOCAL_APIC_OFFSET_Local_APIC_APR 0x90 -#define LOCAL_APIC_OFFSET_Local_APIC_PPR 0xa0 -#define LOCAL_APIC_OFFSET_Local_APIC_EOI 0xb0 -#define LOCAL_APIC_OFFSET_Local_APIC_RRD 0xc0 -#define LOCAL_APIC_OFFSET_Local_APIC_LDR 0xd0 -#define LOCAL_APIC_OFFSET_Local_APIC_DFR 0xe0 -#define LOCAL_APIC_OFFSET_Local_APIC_SVR 0xf0 - -#define LOCAL_APIC_OFFSET_Local_APIC_ISR_31_0 0x100 -#define LOCAL_APIC_OFFSET_Local_APIC_ISR_63_32 0x110 -#define LOCAL_APIC_OFFSET_Local_APIC_ISR_95_64 0x120 -#define LOCAL_APIC_OFFSET_Local_APIC_ISR_127_96 0x130 -#define LOCAL_APIC_OFFSET_Local_APIC_ISR_159_128 0x140 -#define LOCAL_APIC_OFFSET_Local_APIC_ISR_191_160 0x150 -#define LOCAL_APIC_OFFSET_Local_APIC_ISR_223_192 0x160 -#define LOCAL_APIC_OFFSET_Local_APIC_ISR_255_224 0x170 - -#define LOCAL_APIC_OFFSET_Local_APIC_TMR_31_0 0x180 -#define LOCAL_APIC_OFFSET_Local_APIC_TMR_63_32 0x190 -#define LOCAL_APIC_OFFSET_Local_APIC_TMR_95_64 0x1a0 -#define LOCAL_APIC_OFFSET_Local_APIC_TMR_127_96 0x1b0 -#define LOCAL_APIC_OFFSET_Local_APIC_TMR_159_128 0x1c0 -#define LOCAL_APIC_OFFSET_Local_APIC_TMR_191_160 0x1d0 -#define LOCAL_APIC_OFFSET_Local_APIC_TMR_223_192 0x1e0 -#define LOCAL_APIC_OFFSET_Local_APIC_TMR_255_224 0x1f0 - -#define LOCAL_APIC_OFFSET_Local_APIC_IRR_31_0 0x200 -#define LOCAL_APIC_OFFSET_Local_APIC_IRR_63_32 0x210 -#define LOCAL_APIC_OFFSET_Local_APIC_IRR_95_64 0x220 -#define LOCAL_APIC_OFFSET_Local_APIC_IRR_127_96 0x230 -#define LOCAL_APIC_OFFSET_Local_APIC_IRR_159_128 0x240 -#define LOCAL_APIC_OFFSET_Local_APIC_IRR_191_160 0x250 -#define LOCAL_APIC_OFFSET_Local_APIC_IRR_223_192 0x260 -#define LOCAL_APIC_OFFSET_Local_APIC_IRR_255_224 0x270 - -#define LOCAL_APIC_OFFSET_Local_APIC_ESR 0x280 - -// 0x290~0x2e0 Reserved. - -#define LOCAL_APIC_OFFSET_Local_APIC_LVT_CMCI 0x2f0 -#define LOCAL_APIC_OFFSET_Local_APIC_ICR_31_0 0x300 -#define LOCAL_APIC_OFFSET_Local_APIC_ICR_63_32 0x310 -#define LOCAL_APIC_OFFSET_Local_APIC_LVT_TIMER 0x320 -#define LOCAL_APIC_OFFSET_Local_APIC_LVT_THERMAL 0x330 -#define LOCAL_APIC_OFFSET_Local_APIC_LVT_PERFORMANCE_MONITOR 0x340 -#define LOCAL_APIC_OFFSET_Local_APIC_LVT_LINT0 0x350 -#define LOCAL_APIC_OFFSET_Local_APIC_LVT_LINT1 0x360 -#define LOCAL_APIC_OFFSET_Local_APIC_LVT_ERROR 0x370 -// 初始计数寄存器(定时器专用) -#define LOCAL_APIC_OFFSET_Local_APIC_INITIAL_COUNT_REG 0x380 -// 当前计数寄存器(定时器专用) -#define LOCAL_APIC_OFFSET_Local_APIC_CURRENT_COUNT_REG 0x390 -// 0x3A0~0x3D0 Reserved. -// 分频配置寄存器(定时器专用) -#define LOCAL_APIC_OFFSET_Local_APIC_CLKDIV 0x3e0 - -uint32_t RCBA_vaddr = 0; // RCBA寄存器的虚拟地址 - -/* - -1: LVT CMCI -2: LVT Timer -3: LVT Thermal Monitor -4: LVT Performace Counter -5: LVT LINT0 -6: LVT LINT1 -7: LVT Error - -*/ -/** - * LVT表项 - * */ -struct apic_LVT -{ - uint vector : 8, // 0-7位全部置为1 - delivery_mode : 3, // 第[10:8]位置为100, 表示NMI - reserved_1 : 1, // 第11位保留 - delivery_status : 1, // 第12位,投递状态 -> 发送挂起 - polarity : 1, // 第13位,电平触发极性 存在于LINT0,LINT1 - remote_IRR : 1, // 第14位,远程IRR标志位(只读) 存在于LINT0,LINT1 - trigger_mode : 1, // 第15位,触发模式(0位边沿触发,1为电平触发) 存在于LINT0,LINT1 - mask : 1, // 第16位,屏蔽标志位,(0为未屏蔽, 1为已屏蔽) - timer_mode : 2, // 第[18:17]位,定时模式。(00:一次性定时, 01:周期性定时, 10:指定TSC值计数), 存在于定时器寄存器 - reserved_2 : 13; // [31:19]位保留 - -} __attribute((packed)); // 取消结构体的align - -/** - * @brief I/O APIC 的中断定向寄存器的结构体 - * - */ -struct apic_IO_APIC_RTE_entry -{ - unsigned int vector : 8, // 0~7 - deliver_mode : 3, // [10:8] 投递模式默认为NMI - dest_mode : 1, // 11 目标模式(0位物理模式,1为逻辑模式) - deliver_status : 1, // 12 投递状态 - polarity : 1, // 13 电平触发极性 - remote_IRR : 1, // 14 远程IRR标志位(只读) - trigger_mode : 1, // 15 触发模式(0位边沿触发,1为电平触发) - mask : 1, // 16 屏蔽标志位,(0为未屏蔽, 1为已屏蔽) - reserved : 15; // [31:17]位保留 - - union - { - // 物理模式 - struct - { - unsigned int reserved1 : 24, // [55:32] 保留 - phy_dest : 4, // [59:56] APIC ID - reserved2 : 4; // [63:60] 保留 - } physical; - - // 逻辑模式 - struct - { - unsigned int reserved1 : 24, // [55:32] 保留 - logical_dest : 8; // [63:56] 自定义APIC ID - } logical; - } destination; -} __attribute__((packed)); - -// ========== APIC的寄存器的参数定义 ============== -// 投递模式 -#define LOCAL_APIC_FIXED 0 -#define IO_APIC_FIXED 0 -#define ICR_APIC_FIXED 0 - -#define IO_APIC_Lowest_Priority 1 -#define ICR_Lowest_Priority 1 - -#define LOCAL_APIC_SMI 2 -#define APIC_SMI 2 -#define ICR_SMI 2 - -#define LOCAL_APIC_NMI 4 -#define APIC_NMI 4 -#define ICR_NMI 4 - -#define LOCAL_APIC_INIT 5 -#define APIC_INIT 5 -#define ICR_INIT 5 - -#define ICR_Start_up 6 - -#define IO_APIC_ExtINT 7 - -// 时钟模式 -#define APIC_LVT_Timer_One_Shot 0 -#define APIC_LVT_Timer_Periodic 1 -#define APIC_LVT_Timer_TSC_Deadline 2 - -// 屏蔽 -#define UNMASKED 0 -#define MASKED 1 -#define APIC_LVT_INT_MASKED 0x10000UL - -// 触发模式 -#define EDGE_TRIGGER 0 // 边沿触发 -#define Level_TRIGGER 1 // 电平触发 - -// 投递模式 -#define IDLE 0 // 挂起 -#define SEND_PENDING 1 // 发送等待 - -// destination shorthand -#define ICR_No_Shorthand 0 -#define ICR_Self 1 -#define ICR_ALL_INCLUDE_Self 2 -#define ICR_ALL_EXCLUDE_Self 3 - -// 投递目标模式 -#define DEST_PHYSICAL 0 // 物理模式 -#define DEST_LOGIC 1 // 逻辑模式 - -// level -#define ICR_LEVEL_DE_ASSERT 0 -#define ICR_LEVEL_ASSERT 1 - -// 远程IRR标志位, 在处理Local APIC标志位时置位,在收到处理器发来的EOI命令时复位 -#define IRR_RESET 0 -#define IRR_ACCEPT 1 - -// 电平触发极性 -#define POLARITY_HIGH 0 -#define POLARITY_LOW 1 - -/** - * @brief 中断服务程序 - * - * @param rsp 中断栈指针 - * @param number 中断向量号 - */ -void do_IRQ(struct pt_regs *rsp, ul number); -void rs_apic_init_ap(); - -#if ARCH(I386) || ARCH(X86_64) - -// =========== 中断控制操作接口 ============ -void apic_ioapic_enable(ul irq_num); -void apic_ioapic_disable(ul irq_num); -ul apic_ioapic_install(ul irq_num, void *arg); -void apic_ioapic_uninstall(ul irq_num); -void apic_ioapic_edge_ack(ul irq_num); // ioapic边沿触发 应答 - -// void apic_local_apic_level_ack(ul irq_num);// local apic电平触发 应答 -void apic_local_apic_edge_ack(ul irq_num); // local apic边沿触发 应答 -#else -void apic_ioapic_enable(ul irq_num) -{ - while (1) - ; -} -void apic_ioapic_disable(ul irq_num) -{ - while (1) - ; -} -ul apic_ioapic_install(ul irq_num, void *arg) -{ - while (1) - ; -} -void apic_ioapic_uninstall(ul irq_num) -{ - while (1) - ; -} -void apic_ioapic_edge_ack(ul irq_num) -{ - while (1) - ; -} // ioapic边沿触发 应答 - -// void apic_local_apic_level_ack(ul irq_num);// local apic电平触发 应答 -void apic_local_apic_edge_ack(ul irq_num) -{ - while (1) - ; -} // local apic边沿触发 应答 - -#endif - -/** - * @brief 构造RTE Entry结构体 - * - * @param entry 返回的结构体 - * @param vector 中断向量 - * @param deliver_mode 投递模式 - * @param dest_mode 目标模式 - * @param deliver_status 投递状态 - * @param polarity 电平触发极性 - * @param irr 远程IRR标志位(只读) - * @param trigger 触发模式 - * @param mask 屏蔽标志位,(0为未屏蔽, 1为已屏蔽) - * @param dest_apicID 目标apicID - */ -void apic_make_rte_entry(struct apic_IO_APIC_RTE_entry *entry, uint8_t vector, uint8_t deliver_mode, uint8_t dest_mode, - uint8_t deliver_status, uint8_t polarity, uint8_t irr, uint8_t trigger, uint8_t mask, uint8_t dest_apicID); - -#pragma GCC pop_options \ No newline at end of file diff --git a/kernel/src/arch/x86_64/driver/apic/apic_timer.c b/kernel/src/arch/x86_64/driver/apic/apic_timer.c deleted file mode 100644 index 58190bf8..00000000 --- a/kernel/src/arch/x86_64/driver/apic/apic_timer.c +++ /dev/null @@ -1,96 +0,0 @@ -#include "apic_timer.h" -#include -#include -#include -#include - - -// bsp 是否已经完成apic时钟初始化 -static bool bsp_initialized = false; - -extern void rs_apic_timer_install(int irq_num); -extern void rs_apic_timer_uninstall(int irq_num); -extern void rs_apic_timer_enable(int irq_num); -extern void rs_apic_timer_disable(int irq_num); -extern int rs_apic_timer_handle_irq(); - -/** - * @brief 初始化AP核的apic时钟 - * - */ -void apic_timer_ap_core_init() -{ - while (!bsp_initialized) - { - pause(); - } - - apic_timer_init(); -} - -void apic_timer_enable(uint64_t irq_num) -{ - rs_apic_timer_enable(irq_num); -} - -void apic_timer_disable(uint64_t irq_num) -{ - rs_apic_timer_disable(irq_num); -} - -/** - * @brief 安装local apic定时器中断 - * - * @param irq_num 中断向量号 - * @param arg 初始计数值 - * @return uint64_t - */ -uint64_t apic_timer_install(ul irq_num, void *arg) -{ - - rs_apic_timer_install(irq_num); - return 0; -} - -void apic_timer_uninstall(ul irq_num) -{ - rs_apic_timer_uninstall(irq_num); -} - -hardware_intr_controller apic_timer_intr_controller = { - .enable = apic_timer_enable, - .disable = apic_timer_disable, - .install = apic_timer_install, - .uninstall = apic_timer_uninstall, - .ack = apic_local_apic_edge_ack, -}; - -/** - * @brief local apic定时器的中断处理函数 - * - * @param number 中断向量号 - * @param param 参数 - * @param regs 寄存器值 - */ -void apic_timer_handler(uint64_t number, uint64_t param, struct pt_regs *regs) -{ - rs_apic_timer_handle_irq(); -} - -/** - * @brief 初始化local APIC定时器 - * - */ -void apic_timer_init() -{ - kinfo("Initializing apic timer for cpu %d", rs_current_pcb_cpuid()); - io_mfence(); - irq_register(APIC_TIMER_IRQ_NUM, NULL, &apic_timer_handler, 0, &apic_timer_intr_controller, - "apic timer"); - io_mfence(); - if (rs_current_pcb_cpuid() == 0) - { - bsp_initialized = true; - } - kdebug("apic timer init done for cpu %d", rs_current_pcb_cpuid()); -} diff --git a/kernel/src/arch/x86_64/driver/apic/apic_timer.h b/kernel/src/arch/x86_64/driver/apic/apic_timer.h deleted file mode 100644 index 5e8bcd90..00000000 --- a/kernel/src/arch/x86_64/driver/apic/apic_timer.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include -#include "apic.h" - -#define APIC_TIMER_IRQ_NUM 151 - -/** - * @brief 初始化local APIC定时器 - * - */ -void apic_timer_init(); - -void apic_timer_ap_core_init(); diff --git a/kernel/src/arch/x86_64/driver/apic/apic_timer.rs b/kernel/src/arch/x86_64/driver/apic/apic_timer.rs index 45403191..aaaae53b 100644 --- a/kernel/src/arch/x86_64/driver/apic/apic_timer.rs +++ b/kernel/src/arch/x86_64/driver/apic/apic_timer.rs @@ -1,42 +1,111 @@ use core::cell::RefCell; use crate::arch::driver::tsc::TSCManager; -use crate::include::bindings::bindings::APIC_TIMER_IRQ_NUM; +use crate::arch::interrupt::TrapFrame; +use crate::driver::base::device::DeviceId; +use crate::exception::irqdata::{IrqHandlerData, IrqLineStatus}; +use crate::exception::irqdesc::{ + irq_desc_manager, IrqDesc, IrqFlowHandler, IrqHandleFlags, IrqHandler, IrqReturn, +}; +use crate::exception::manage::irq_manager; +use crate::exception::IrqNumber; use crate::kdebug; use crate::mm::percpu::PerCpu; use crate::sched::core::sched_update_jiffies; use crate::smp::core::smp_get_processor_id; +use crate::smp::cpu::ProcessorId; use crate::time::clocksource::HZ; +use alloc::string::ToString; +use alloc::sync::Arc; pub use drop; use system_error::SystemError; use x86::cpuid::cpuid; use x86::msr::{wrmsr, IA32_X2APIC_DIV_CONF, IA32_X2APIC_INIT_COUNT}; +use super::lapic_vector::local_apic_chip; use super::xapic::XApicOffset; use super::{CurrentApic, LVTRegister, LocalAPIC, LVT}; -static mut LOCAL_APIC_TIMERS: [RefCell; PerCpu::MAX_CPU_NUM] = - [const { RefCell::new(LocalApicTimer::new()) }; PerCpu::MAX_CPU_NUM]; +pub const APIC_TIMER_IRQ_NUM: IrqNumber = IrqNumber::new(151); +static mut LOCAL_APIC_TIMERS: [RefCell; PerCpu::MAX_CPU_NUM as usize] = + [const { RefCell::new(LocalApicTimer::new()) }; PerCpu::MAX_CPU_NUM as usize]; + +#[allow(dead_code)] #[inline(always)] -pub(super) fn local_apic_timer_instance(cpu_id: u32) -> core::cell::Ref<'static, LocalApicTimer> { - unsafe { LOCAL_APIC_TIMERS[cpu_id as usize].borrow() } +pub(super) fn local_apic_timer_instance( + cpu_id: ProcessorId, +) -> core::cell::Ref<'static, LocalApicTimer> { + unsafe { LOCAL_APIC_TIMERS[cpu_id.data() as usize].borrow() } } #[inline(always)] pub(super) fn local_apic_timer_instance_mut( - cpu_id: u32, + cpu_id: ProcessorId, ) -> core::cell::RefMut<'static, LocalApicTimer> { - unsafe { LOCAL_APIC_TIMERS[cpu_id as usize].borrow_mut() } + unsafe { LOCAL_APIC_TIMERS[cpu_id.data() as usize].borrow_mut() } +} + +#[derive(Debug)] +struct LocalApicTimerHandler; + +impl IrqHandler for LocalApicTimerHandler { + fn handle( + &self, + _irq: IrqNumber, + _static_data: Option<&dyn IrqHandlerData>, + _dynamic_data: Option>, + ) -> Result { + // empty (只是为了让编译通过,不会被调用到。真正的处理函数在LocalApicTimerIrqFlowHandler中) + Ok(IrqReturn::NotHandled) + } +} + +#[derive(Debug)] +struct LocalApicTimerIrqFlowHandler; + +impl IrqFlowHandler for LocalApicTimerIrqFlowHandler { + fn handle(&self, _irq_desc: &Arc, _trap_frame: &mut TrapFrame) { + LocalApicTimer::handle_irq().ok(); + CurrentApic.send_eoi(); + } +} + +pub fn apic_timer_init() { + irq_manager() + .request_irq( + APIC_TIMER_IRQ_NUM, + "LocalApic".to_string(), + &LocalApicTimerHandler, + IrqHandleFlags::IRQF_SHARED | IrqHandleFlags::IRQF_PERCPU, + Some(DeviceId::new(Some("lapic timer"), None).unwrap()), + ) + .expect("Apic timer init failed"); + + LocalApicTimerIntrController.install(); + LocalApicTimerIntrController.enable(); +} + +/// 初始化本地APIC定时器的中断描述符 +#[inline(never)] +pub(super) fn local_apic_timer_irq_desc_init() { + let desc = irq_desc_manager().lookup(APIC_TIMER_IRQ_NUM).unwrap(); + let irq_data: Arc = desc.irq_data(); + let mut chip_info_guard = irq_data.chip_info_write_irqsave(); + chip_info_guard.set_chip(Some(local_apic_chip().clone())); + + desc.modify_status(IrqLineStatus::IRQ_LEVEL, IrqLineStatus::empty()); + drop(chip_info_guard); + desc.set_handler(&LocalApicTimerIrqFlowHandler); } /// 初始化BSP的APIC定时器 /// fn init_bsp_apic_timer() { kdebug!("init_bsp_apic_timer"); - assert!(smp_get_processor_id() == 0); - let mut local_apic_timer = local_apic_timer_instance_mut(0); + assert!(smp_get_processor_id().data() == 0); + let mut local_apic_timer = local_apic_timer_instance_mut(ProcessorId::new(0)); local_apic_timer.init( LocalApicTimerMode::Periodic, LocalApicTimer::periodic_default_initial_count(), @@ -48,7 +117,7 @@ fn init_bsp_apic_timer() { fn init_ap_apic_timer() { kdebug!("init_ap_apic_timer"); let cpu_id = smp_get_processor_id(); - assert!(cpu_id != 0); + assert!(cpu_id.data() != 0); let mut local_apic_timer = local_apic_timer_instance_mut(cpu_id); local_apic_timer.init( @@ -62,15 +131,16 @@ fn init_ap_apic_timer() { pub(super) struct LocalApicTimerIntrController; impl LocalApicTimerIntrController { - pub(super) fn install(&self, _irq_num: u8) { + pub(super) fn install(&self) { kdebug!("LocalApicTimerIntrController::install"); - if smp_get_processor_id() == 0 { + if smp_get_processor_id().data() == 0 { init_bsp_apic_timer(); } else { init_ap_apic_timer(); } } + #[allow(dead_code)] pub(super) fn uninstall(&self) { let cpu_id = smp_get_processor_id(); let local_apic_timer = local_apic_timer_instance(cpu_id); @@ -157,7 +227,11 @@ impl LocalApicTimer { self.mode = LocalApicTimerMode::Periodic; self.set_divisor(divisor); self.set_initial_cnt(initial_count); - self.setup_lvt(APIC_TIMER_IRQ_NUM as u8, true, LocalApicTimerMode::Periodic); + self.setup_lvt( + APIC_TIMER_IRQ_NUM.data() as u8, + true, + LocalApicTimerMode::Periodic, + ); } fn setup_lvt(&mut self, vector: u8, mask: bool, mode: LocalApicTimerMode) { @@ -200,9 +274,9 @@ impl LocalApicTimer { return (res.ecx & (1 << 24)) != 0; } - pub(super) fn handle_irq() -> Result<(), SystemError> { + pub(super) fn handle_irq() -> Result { sched_update_jiffies(); - return Ok(()); + return Ok(IrqReturn::Handled); } } diff --git a/kernel/src/arch/x86_64/driver/apic/c_adapter.rs b/kernel/src/arch/x86_64/driver/apic/c_adapter.rs index a789a9b2..ca18d126 100644 --- a/kernel/src/arch/x86_64/driver/apic/c_adapter.rs +++ b/kernel/src/arch/x86_64/driver/apic/c_adapter.rs @@ -1,43 +1,4 @@ -use super::{ - apic_timer::{LocalApicTimer, LocalApicTimerIntrController}, - ioapic::{ioapic_disable, ioapic_enable, ioapic_install, ioapic_uninstall}, - CurrentApic, LocalAPIC, -}; - -#[no_mangle] -unsafe extern "C" fn rs_apic_timer_install(irq_num: u8) { - LocalApicTimerIntrController.install(irq_num); -} - -#[no_mangle] -unsafe extern "C" fn rs_apic_timer_uninstall(_irq_num: u8) { - LocalApicTimerIntrController.uninstall(); -} - -#[no_mangle] -unsafe extern "C" fn rs_apic_timer_enable(_irq_num: u8) { - LocalApicTimerIntrController.enable(); -} - -#[no_mangle] -unsafe extern "C" fn rs_apic_timer_disable(_irq_num: u8) { - LocalApicTimerIntrController.disable(); -} - -#[no_mangle] -unsafe extern "C" fn rs_apic_local_apic_edge_ack(_irq_num: u8) { - CurrentApic.send_eoi(); -} - -/// 初始化bsp处理器的apic -#[no_mangle] -pub extern "C" fn rs_apic_init_bsp() -> i32 { - if CurrentApic.init_current_cpu() { - return 0; - } - - return -1; -} +use super::{CurrentApic, LocalAPIC}; #[no_mangle] pub extern "C" fn rs_apic_init_ap() -> i32 { @@ -47,38 +8,3 @@ pub extern "C" fn rs_apic_init_ap() -> i32 { return -1; } - -#[no_mangle] -unsafe extern "C" fn rs_ioapic_install( - vector: u8, - dest: u8, - level_triggered: bool, - active_high: bool, - dest_logic: bool, -) -> i32 { - return ioapic_install(vector, dest, level_triggered, active_high, dest_logic) - .map(|_| 0) - .unwrap_or_else(|e| e.to_posix_errno()); -} - -#[no_mangle] -unsafe extern "C" fn rs_ioapic_uninstall(vector: u8) { - ioapic_uninstall(vector); -} - -#[no_mangle] -unsafe extern "C" fn rs_ioapic_enable(vector: u8) { - ioapic_enable(vector); -} - -#[no_mangle] -unsafe extern "C" fn rs_ioapic_disable(vector: u8) { - ioapic_disable(vector); -} - -#[no_mangle] -unsafe extern "C" fn rs_apic_timer_handle_irq(_irq_num: u8) -> i32 { - return LocalApicTimer::handle_irq() - .map(|_| 0) - .unwrap_or_else(|e| e.to_posix_errno()); -} diff --git a/kernel/src/arch/x86_64/driver/apic/hw_irq.rs b/kernel/src/arch/x86_64/driver/apic/hw_irq.rs new file mode 100644 index 00000000..df9a10a7 --- /dev/null +++ b/kernel/src/arch/x86_64/driver/apic/hw_irq.rs @@ -0,0 +1,9 @@ +use crate::{exception::HardwareIrqNumber, int_like}; + +int_like!(ApicId, u32); + +#[derive(Debug)] +pub(super) struct HardwareIrqConfig { + pub apic_id: ApicId, + pub vector: HardwareIrqNumber, +} diff --git a/kernel/src/arch/x86_64/driver/apic/ioapic.rs b/kernel/src/arch/x86_64/driver/apic/ioapic.rs index cbfeae2a..16152402 100644 --- a/kernel/src/arch/x86_64/driver/apic/ioapic.rs +++ b/kernel/src/arch/x86_64/driver/apic/ioapic.rs @@ -1,16 +1,26 @@ use core::ptr::NonNull; use acpi::madt::Madt; +use alloc::sync::Arc; use bit_field::BitField; use bitflags::bitflags; use system_error::SystemError; use crate::{ driver::acpi::acpi_manager, + exception::{ + handle::{edge_irq_handler, fast_eoi_irq_handler}, + irqchip::{IrqChip, IrqChipData, IrqChipFlags, IrqChipSetMaskResult, IrqChipState}, + irqdata::{IrqData, IrqLineStatus}, + irqdesc::{irq_desc_manager, IrqDesc, IrqFlowHandler}, + manage::irq_manager, + IrqNumber, + }, kdebug, kinfo, libs::{ + cpumask::CpuMask, once::Once, - spinlock::SpinLock, + spinlock::{SpinLock, SpinLockGuard}, volatile::{volwrite, Volatile}, }, mm::{ @@ -22,12 +32,18 @@ use crate::{ use super::{CurrentApic, LocalAPIC}; static mut __IOAPIC: Option> = None; +static mut IOAPIC_IR_CHIP: Option> = None; #[allow(non_snake_case)] fn IOAPIC() -> &'static SpinLock { unsafe { __IOAPIC.as_ref().unwrap() } } +#[inline(always)] +pub(super) fn ioapic_ir_chip() -> Arc { + unsafe { IOAPIC_IR_CHIP.as_ref().unwrap().clone() } +} + #[allow(dead_code)] pub struct IoApic { reg: *mut u32, @@ -253,6 +269,12 @@ impl IoApic { unsafe { (self.read(REG_VER).get_bits(16..24) + 1) as u8 } } + pub fn pending(&mut self, irq: u8) -> bool { + let rte_index = Self::vector_rte_index(irq); + let data = unsafe { self.read(REG_TABLE + 2 * rte_index) }; + data & (1 << 12) != 0 + } + fn vector_rte_index(irq_num: u8) -> u8 { assert!(irq_num >= Self::VECTOR_BASE); irq_num - Self::VECTOR_BASE @@ -272,12 +294,6 @@ impl IoApic { volwrite!(p, virt_eoi, irq_num as u32); } } - - /// 边沿响应 - #[allow(dead_code)] - fn edge_ack(&mut self, _irq_num: u8) { - CurrentApic.send_eoi(); - } } /// Register index: ID @@ -307,15 +323,126 @@ bitflags! { } } -pub fn ioapic_init() { +#[derive(Debug)] +struct IoApicChipData { + inner: SpinLock, +} + +impl IrqChipData for IoApicChipData { + fn as_any_ref(&self) -> &dyn core::any::Any { + self + } +} + +impl IoApicChipData { + const DEFAULT: Self = Self::new(0, 0, 0, false, false, false, true); + + const fn new( + rte_index: u8, + vector: u8, + dest: u8, + level_triggered: bool, + active_high: bool, + dest_logic: bool, + mask: bool, + ) -> Self { + IoApicChipData { + inner: SpinLock::new(InnerIoApicChipData { + rte_index, + vector, + dest, + level_triggered, + active_high, + dest_logic, + mask, + }), + } + } + + fn inner(&self) -> SpinLockGuard { + self.inner.lock_irqsave() + } +} + +#[derive(Debug)] +struct InnerIoApicChipData { + rte_index: u8, + vector: u8, + dest: u8, + level_triggered: bool, + active_high: bool, + dest_logic: bool, + mask: bool, +} + +impl InnerIoApicChipData { + /// 把中断数据同步到芯片 + fn sync_to_chip(&self) -> Result<(), SystemError> { + ioapic_install( + self.vector, + self.dest, + self.level_triggered, + self.active_high, + self.dest_logic, + self.mask, + ) + } +} + +#[inline(never)] +pub fn ioapic_init(ignore: &'static [IrqNumber]) { kinfo!("Initializing ioapic..."); let ioapic = unsafe { IoApic::new() }; unsafe { __IOAPIC = Some(SpinLock::new(ioapic)); } + unsafe { + IOAPIC_IR_CHIP = Some(Arc::new(IoApicChip)); + } + + // 绑定irqchip + for i in 32..256 { + let irq = IrqNumber::new(i); + + if ignore.contains(&irq) { + continue; + } + + let desc = irq_desc_manager().lookup(irq).unwrap(); + let irq_data = desc.irq_data(); + let mut chip_info_guard = irq_data.chip_info_write_irqsave(); + chip_info_guard.set_chip(Some(ioapic_ir_chip())); + let chip_data = IoApicChipData::DEFAULT; + chip_data.inner().rte_index = IoApic::vector_rte_index(i as u8); + chip_data.inner().vector = i as u8; + chip_info_guard.set_chip_data(Some(Arc::new(chip_data))); + drop(chip_info_guard); + let level = irq_data.is_level_type(); + + register_handler(&desc, level); + } + kinfo!("IO Apic initialized."); } +fn register_handler(desc: &Arc, level_triggered: bool) { + let fasteoi: bool; + if level_triggered { + desc.modify_status(IrqLineStatus::empty(), IrqLineStatus::IRQ_LEVEL); + fasteoi = true; + } else { + desc.modify_status(IrqLineStatus::IRQ_LEVEL, IrqLineStatus::empty()); + fasteoi = false; + } + + let handler: &dyn IrqFlowHandler = if fasteoi { + fast_eoi_irq_handler() + } else { + edge_irq_handler() + }; + desc.set_handler(handler); +} + /// 安装中断 /// /// ## 参数 @@ -326,12 +453,13 @@ pub fn ioapic_init() { /// * `active_high` - 是否为高电平有效 /// * `dest_logic` - 是否为逻辑模式 /// * `mask` - 是否屏蔽 -pub(super) fn ioapic_install( +fn ioapic_install( vector: u8, dest: u8, level_triggered: bool, active_high: bool, dest_logic: bool, + mask: bool, ) -> Result<(), SystemError> { let rte_index = IoApic::vector_rte_index(vector); return IOAPIC().lock_irqsave().install( @@ -341,24 +469,190 @@ pub(super) fn ioapic_install( level_triggered, active_high, dest_logic, - true, + mask, ); } -/// 卸载中断 -pub(super) fn ioapic_uninstall(vector: u8) { - let rte_index = IoApic::vector_rte_index(vector); - IOAPIC().lock_irqsave().disable(rte_index); -} +/// IoApic中断芯片 +/// +/// https://code.dragonos.org.cn/xref/linux-6.1.9/arch/x86/kernel/apic/io_apic.c#1994 +#[derive(Debug)] +struct IoApicChip; -/// 使能中断 -pub(super) fn ioapic_enable(vector: u8) { - let rte_index = IoApic::vector_rte_index(vector); - IOAPIC().lock_irqsave().enable(rte_index); -} +impl IrqChip for IoApicChip { + fn name(&self) -> &'static str { + "IR-IO-APIC" + } -/// 禁用中断 -pub(super) fn ioapic_disable(vector: u8) { - let rte_index = IoApic::vector_rte_index(vector); - IOAPIC().lock_irqsave().disable(rte_index); + fn irq_startup(&self, irq: &Arc) -> Result<(), SystemError> { + self.irq_unmask(irq) + } + + fn irq_mask(&self, irq: &Arc) -> Result<(), SystemError> { + let binding = irq + .chip_info_read_irqsave() + .chip_data() + .ok_or(SystemError::EINVAL)?; + let chip_data = binding + .as_any_ref() + .downcast_ref::() + .ok_or(SystemError::EINVAL)?; + + let mut chip_data_inner = chip_data.inner(); + chip_data_inner.mask = true; + chip_data_inner.sync_to_chip().ok(); + + drop(chip_data_inner); + + return Ok(()); + } + + fn can_set_affinity(&self) -> bool { + true + } + + fn can_set_flow_type(&self) -> bool { + true + } + + fn irq_set_type( + &self, + irq: &Arc, + flow_type: IrqLineStatus, + ) -> Result { + let binding = irq + .chip_info_read_irqsave() + .chip_data() + .ok_or(SystemError::EINVAL)?; + let chip_data = binding + .as_any_ref() + .downcast_ref::() + .ok_or(SystemError::EINVAL)?; + let mut chip_data_inner = chip_data.inner(); + + let level_triggered = flow_type.is_level_type(); + let active_high = flow_type.is_level_high().unwrap_or(false); + chip_data_inner.active_high = active_high; + chip_data_inner.level_triggered = level_triggered; + chip_data_inner.sync_to_chip()?; + + return Ok(IrqChipSetMaskResult::SetMaskOk); + } + + fn irq_set_affinity( + &self, + irq: &Arc, + cpu: &CpuMask, + _force: bool, + ) -> Result { + // 使用mask的第1个可用CPU + let dest = (cpu.first().ok_or(SystemError::EINVAL)?.data() & 0xff) as u8; + + let binding = irq + .chip_info_read_irqsave() + .chip_data() + .ok_or(SystemError::EINVAL)?; + let chip_data = binding + .as_any_ref() + .downcast_ref::() + .ok_or(SystemError::EINVAL)?; + + let mut chip_data_inner = chip_data.inner(); + let origin_dest = chip_data_inner.dest; + if origin_dest == dest { + return Ok(IrqChipSetMaskResult::SetMaskOk); + } + + chip_data_inner.dest = dest; + + chip_data_inner.sync_to_chip()?; + + return Ok(IrqChipSetMaskResult::SetMaskOk); + } + + fn irq_unmask(&self, irq: &Arc) -> Result<(), SystemError> { + IOAPIC() + .lock_irqsave() + .enable(IoApic::vector_rte_index(irq.irq().data() as u8)); + Ok(()) + } + + fn can_mask_ack(&self) -> bool { + true + } + + fn irq_mask_ack(&self, irq: &Arc) { + self.irq_mask(irq).ok(); + self.irq_eoi(irq); + } + + fn irq_eoi(&self, irq: &Arc) { + if irq.is_level_type() { + IOAPIC().lock_irqsave().level_ack(irq.irq().data() as u8); + } else { + CurrentApic.send_eoi(); + } + } + + fn retrigger(&self, irq_data: &Arc) -> Result<(), SystemError> { + irq_manager().irq_chip_retrigger_hierarchy(irq_data) + } + + fn irqchip_state(&self, irq: &Arc, which: IrqChipState) -> Result { + let binding = irq + .chip_info_read_irqsave() + .chip_data() + .ok_or(SystemError::EINVAL)?; + let chip_data = binding + .as_any_ref() + .downcast_ref::() + .ok_or(SystemError::EINVAL)?; + + match which { + IrqChipState::Pending => { + return Ok(IOAPIC().lock_irqsave().pending(irq.irq().data() as u8)); + } + IrqChipState::Active => { + let chip_data_inner = chip_data.inner(); + return Ok(!chip_data_inner.mask); + } + IrqChipState::Masked => { + let chip_data_inner = chip_data.inner(); + return Ok(chip_data_inner.mask); + } + IrqChipState::LineLevel => { + let chip_data_inner = chip_data.inner(); + return Ok(chip_data_inner.active_high); + } + #[allow(unreachable_patterns)] + _ => { + return Err(SystemError::EINVAL); + } + } + } + + fn irq_disable(&self, irq: &Arc) { + let binding = irq + .chip_info_read_irqsave() + .chip_data() + .ok_or(SystemError::EINVAL) + .unwrap(); + let chip_data = binding + .as_any_ref() + .downcast_ref::() + .ok_or(SystemError::EINVAL) + .unwrap(); + let mut chip_data_inner = chip_data.inner(); + chip_data_inner.mask = true; + chip_data_inner.sync_to_chip().ok(); + } + + fn irq_ack(&self, irq_data: &Arc) { + // irq_manager().irq_chip_ack_parent(irq_data); + self.irq_eoi(irq_data); + } + + fn flags(&self) -> IrqChipFlags { + IrqChipFlags::IRQCHIP_SKIP_SET_WAKE | IrqChipFlags::IRQCHIP_AFFINITY_PRE_STARTUP + } } diff --git a/kernel/src/arch/x86_64/driver/apic/lapic_vector.rs b/kernel/src/arch/x86_64/driver/apic/lapic_vector.rs new file mode 100644 index 00000000..51fad236 --- /dev/null +++ b/kernel/src/arch/x86_64/driver/apic/lapic_vector.rs @@ -0,0 +1,289 @@ +use core::intrinsics::unlikely; + +use alloc::{string::ToString, sync::Arc}; +use intertrait::CastFrom; +use system_error::SystemError; + +use crate::{ + arch::{ + driver::apic::{ + apic_timer::{local_apic_timer_irq_desc_init, APIC_TIMER_IRQ_NUM}, + ioapic::ioapic_init, + }, + interrupt::{ + entry::arch_setup_interrupt_gate, + ipi::{arch_ipi_handler_init, send_ipi, IPI_NUM_FLUSH_TLB, IPI_NUM_KICK_CPU}, + msi::{X86MsiAddrHi, X86MsiAddrLoNormal, X86MsiDataNormal, X86_MSI_BASE_ADDRESS_LOW}, + }, + }, + driver::open_firmware::device_node::DeviceNode, + exception::{ + ipi::{IpiKind, IpiTarget}, + irqchip::{IrqChip, IrqChipData, IrqChipFlags}, + irqdata::IrqData, + irqdomain::{irq_domain_manager, IrqDomain, IrqDomainBusToken, IrqDomainOps}, + msi::MsiMsg, + HardwareIrqNumber, IrqNumber, + }, + kwarn, + libs::spinlock::{SpinLock, SpinLockGuard}, + smp::{core::smp_get_processor_id, cpu::ProcessorId}, +}; + +use super::{hw_irq::HardwareIrqConfig, CurrentApic, LocalAPIC}; + +static mut LOCAL_APIC_CHIP: Option> = None; + +pub fn local_apic_chip() -> &'static Arc { + unsafe { LOCAL_APIC_CHIP.as_ref().unwrap() } +} + +#[derive(Debug)] +pub struct LocalApicChip { + inner: SpinLock, +} + +impl LocalApicChip { + pub fn new() -> Self { + Self { + inner: SpinLock::new(InnerIrqChip { + flags: IrqChipFlags::empty(), + }), + } + } +} + +impl IrqChip for LocalApicChip { + fn name(&self) -> &'static str { + "APIC" + } + + fn can_set_flow_type(&self) -> bool { + false + } + + fn irq_disable(&self, _irq: &Arc) {} + + fn irq_ack(&self, _irq: &Arc) { + CurrentApic.send_eoi(); + } + + fn can_set_affinity(&self) -> bool { + false + } + + fn can_mask_ack(&self) -> bool { + false + } + + fn irq_enable(&self, _irq: &Arc) -> Result<(), SystemError> { + // 这里临时处理,后续需要修改 + return Ok(()); + } + + fn irq_unmask(&self, _irq: &Arc) -> Result<(), SystemError> { + Ok(()) + } + + fn irq_compose_msi_msg(&self, irq: &Arc, msg: &mut MsiMsg) { + let chip_data = irq.chip_info_read_irqsave().chip_data().unwrap(); + let apicd = chip_data.ref_any().downcast_ref::().unwrap(); + let cfg = &apicd.inner().hw_irq_cfg; + irq_msi_compose_msg(cfg, msg, false); + } + + fn retrigger(&self, irq: &Arc) -> Result<(), SystemError> { + let chip_data = irq + .chip_info_read_irqsave() + .chip_data() + .ok_or(SystemError::EINVAL)?; + let apicd = chip_data + .ref_any() + .downcast_ref::() + .ok_or(SystemError::EINVAL)?; + let inner = apicd.inner(); + + send_ipi( + IpiKind::SpecVector(inner.vector), + IpiTarget::Specified(inner.cpu), + ); + + Ok(()) + } + + fn flags(&self) -> IrqChipFlags { + self.inner.lock_irqsave().flags + } +} + +#[derive(Debug)] +struct InnerIrqChip { + flags: IrqChipFlags, +} + +#[derive(Debug)] +struct ApicChipData { + inner: SpinLock, +} + +impl ApicChipData { + #[allow(dead_code)] + pub fn new( + hw_irq_cfg: HardwareIrqConfig, + irq: IrqNumber, + vector: HardwareIrqNumber, + cpu: ProcessorId, + ) -> Self { + Self { + inner: SpinLock::new(InnerApicChipData { + hw_irq_cfg, + irq, + vector, + prev_vector: None, + cpu, + prev_cpu: None, + status: ApicChipStatus::empty(), + }), + } + } + + pub fn inner(&self) -> SpinLockGuard { + self.inner.lock_irqsave() + } +} + +#[allow(dead_code)] +#[derive(Debug)] +struct InnerApicChipData { + hw_irq_cfg: HardwareIrqConfig, + irq: IrqNumber, + vector: HardwareIrqNumber, + prev_vector: Option, + cpu: ProcessorId, + prev_cpu: Option, + status: ApicChipStatus, +} + +impl IrqChipData for ApicChipData { + fn as_any_ref(&self) -> &dyn core::any::Any { + self + } +} + +bitflags! { + pub struct ApicChipStatus: u32 { + const MOVE_IN_PROGRESS = 1 << 0; + const IS_MANAGED = 1 << 1; + const CAN_RESERVE = 1 << 2; + const HAS_RESERVED = 1 << 3; + } +} + +pub(super) fn irq_msi_compose_msg(cfg: &HardwareIrqConfig, msg: &mut MsiMsg, dmar: bool) { + *msg = MsiMsg::new_zeroed(); + + let arch_data = X86MsiDataNormal::new() + .with_delivery_mode(x86::apic::DeliveryMode::Fixed as u8) + .with_vector((cfg.vector.data() & 0xff) as u8); + let mut address_lo = X86MsiAddrLoNormal::new() + .with_base_address(X86_MSI_BASE_ADDRESS_LOW) + .with_dest_mode_logical(false) + .with_destid_0_7(cfg.apic_id.data() & 0xff); + + let mut address_hi = X86MsiAddrHi::new(); + + /* + * 只有IOMMU本身可以使用将目标APIC ID放入地址的高位的技术。 + * 任何其他尝试这样做的东西都只是在写内存,并且需要IR来 + * 寻址不能在正常的32位地址范围内0xFFExxxxx寻址的APIC。 + * 这通常是8位,但一些虚拟化程序允许在位5-11使用扩展的目的地ID字段, + * 总共支持15位的APIC ID。 + */ + if dmar { + address_hi.set_destid_8_31(cfg.apic_id.data() >> 8); + } else if cfg.apic_id.data() < 0x8000 { + // todo: 判断vmx是否支持 extended destination mode + // 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/arch/x86/kernel/apic/apic.c?fi=__irq_msi_compose_msg#2580 + address_lo.set_virt_destid_8_14(cfg.apic_id.data() >> 8); + } else { + if unlikely(cfg.apic_id.data() > 0xff) { + kwarn!( + "irq_msi_compose_msg: Invalid APIC ID: {}", + cfg.apic_id.data() + ); + } + } + msg.address_hi = address_hi.into(); + msg.address_lo = address_lo.into(); + msg.data = arch_data.into(); +} + +static mut X86_VECTOR_DOMAIN: Option> = None; + +#[inline(always)] +#[allow(dead_code)] +pub fn x86_vector_domain() -> &'static Arc { + unsafe { X86_VECTOR_DOMAIN.as_ref().unwrap() } +} + +#[inline(never)] +pub fn arch_early_irq_init() -> Result<(), SystemError> { + let vec_domain = irq_domain_manager() + .create_and_add( + "VECTOR".to_string(), + &X86VectorDomainOps, + IrqNumber::new(32), + HardwareIrqNumber::new(32), + 223, + ) + .ok_or(SystemError::ENOMEM)?; + irq_domain_manager().set_default_domain(vec_domain.clone()); + unsafe { X86_VECTOR_DOMAIN = Some(vec_domain) }; + + let apic_chip = Arc::new(LocalApicChip::new()); + + unsafe { LOCAL_APIC_CHIP = Some(apic_chip) }; + + // todo: add vector matrix + // 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/arch/x86/kernel/apic/vector.c#803 + kwarn!("arch_early_irq_init: todo: add vector matrix"); + + local_apic_timer_irq_desc_init(); + arch_ipi_handler_init(); + CurrentApic.init_current_cpu(); + if smp_get_processor_id().data() == 0 { + unsafe { arch_setup_interrupt_gate() }; + ioapic_init(&[APIC_TIMER_IRQ_NUM, IPI_NUM_KICK_CPU, IPI_NUM_FLUSH_TLB]); + } + return Ok(()); +} + +/// x86的中断域操作 +/// +/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/arch/x86/kernel/apic/vector.c#693 +#[derive(Debug)] +struct X86VectorDomainOps; + +impl IrqDomainOps for X86VectorDomainOps { + fn match_node( + &self, + _irq_domain: &Arc, + _device_node: &Arc, + _bus_token: IrqDomainBusToken, + ) -> bool { + todo!() + } + + fn map( + &self, + _irq_domain: &Arc, + _hwirq: HardwareIrqNumber, + _virq: IrqNumber, + ) -> Result<(), SystemError> { + Err(SystemError::ENOSYS) + } + + fn unmap(&self, _irq_domain: &Arc, _virq: IrqNumber) { + todo!() + } +} diff --git a/kernel/src/arch/x86_64/driver/apic/mod.rs b/kernel/src/arch/x86_64/driver/apic/mod.rs index 10109506..e2831463 100644 --- a/kernel/src/arch/x86_64/driver/apic/mod.rs +++ b/kernel/src/arch/x86_64/driver/apic/mod.rs @@ -6,7 +6,7 @@ use x86::{apic::Icr, msr::IA32_APIC_BASE}; use crate::{ arch::{ - driver::apic::{ioapic::ioapic_init, x2apic::X2Apic, xapic::XApic}, + driver::apic::{hw_irq::ApicId, x2apic::X2Apic, xapic::XApic}, io::PortIOArch, CurrentPortIOArch, }, @@ -22,7 +22,9 @@ use self::{ pub mod apic_timer; mod c_adapter; +pub mod hw_irq; pub mod ioapic; +pub mod lapic_vector; pub mod x2apic; pub mod xapic; @@ -63,7 +65,7 @@ pub trait LocalAPIC { fn max_lvt_entry(&self) -> u8; /// @brief 获取当前处理器的APIC ID - fn id(&self) -> u32; + fn id(&self) -> ApicId; /// @brief 设置LVT寄存器 /// @@ -481,20 +483,20 @@ impl LocalAPIC for CurrentApic { fn init_current_cpu(&mut self) -> bool { let cpu_id = smp_get_processor_id(); - if cpu_id == 0 { + if cpu_id.data() == 0 { unsafe { self.mask8259a(); } } - kinfo!("Initializing apic for cpu {}", cpu_id); + kinfo!("Initializing apic for cpu {:?}", cpu_id); if X2Apic::support() && X2Apic.init_current_cpu() { - if cpu_id == 0 { + if cpu_id.data() == 0 { LOCAL_APIC_ENABLE_TYPE.store(LocalApicEnableType::X2Apic, Ordering::SeqCst); } - kinfo!("x2APIC initialized for cpu {}", cpu_id); + kinfo!("x2APIC initialized for cpu {:?}", cpu_id); } else { kinfo!("x2APIC not supported or failed to initialize, fallback to xAPIC."); - if cpu_id == 0 { + if cpu_id.data() == 0 { LOCAL_APIC_ENABLE_TYPE.store(LocalApicEnableType::XApic, Ordering::SeqCst); } let apic_base = @@ -512,11 +514,9 @@ impl LocalAPIC for CurrentApic { xapic.init_current_cpu(); } - kinfo!("xAPIC initialized for cpu {}", cpu_id); - } - if cpu_id == 0 { - ioapic_init(); + kinfo!("xAPIC initialized for cpu {:?}", cpu_id); } + kinfo!("Apic initialized."); return true; } @@ -567,7 +567,7 @@ impl LocalAPIC for CurrentApic { } } - fn id(&self) -> u32 { + fn id(&self) -> ApicId { if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic { return X2Apic.id(); } else { @@ -575,7 +575,7 @@ impl LocalAPIC for CurrentApic { .borrow() .as_ref() .map(|xapic| xapic.id()) - .unwrap_or(0); + .unwrap_or(ApicId::new(0)); } } diff --git a/kernel/src/arch/x86_64/driver/apic/x2apic.rs b/kernel/src/arch/x86_64/driver/apic/x2apic.rs index 3f24aea4..63fd105c 100644 --- a/kernel/src/arch/x86_64/driver/apic/x2apic.rs +++ b/kernel/src/arch/x86_64/driver/apic/x2apic.rs @@ -5,7 +5,7 @@ use x86::msr::{ use crate::{kdebug, kinfo}; -use super::{LVTRegister, LocalAPIC, LVT}; +use super::{hw_irq::ApicId, LVTRegister, LocalAPIC, LVT}; #[derive(Debug)] pub struct X2Apic; @@ -84,8 +84,8 @@ impl LocalAPIC for X2Apic { } /// 获取 x2APIC 的 APIC ID - fn id(&self) -> u32 { - unsafe { rdmsr(IA32_X2APIC_APICID.into()) as u32 } + fn id(&self) -> ApicId { + unsafe { ApicId::new(rdmsr(IA32_X2APIC_APICID.into()) as u32) } } /// 设置 Local Vector Table (LVT) 寄存器 diff --git a/kernel/src/arch/x86_64/driver/apic/xapic.rs b/kernel/src/arch/x86_64/driver/apic/xapic.rs index 4ec2b3a1..dd940db2 100644 --- a/kernel/src/arch/x86_64/driver/apic/xapic.rs +++ b/kernel/src/arch/x86_64/driver/apic/xapic.rs @@ -14,15 +14,15 @@ use crate::{ smp::core::smp_get_processor_id, }; -use super::{LVTRegister, LocalAPIC, LVT}; +use super::{hw_irq::ApicId, LVTRegister, LocalAPIC, LVT}; /// per-cpu的xAPIC的MMIO空间起始地址 -static mut XAPIC_INSTANCES: [RefCell>; PerCpu::MAX_CPU_NUM] = - [const { RefCell::new(None) }; PerCpu::MAX_CPU_NUM]; +static mut XAPIC_INSTANCES: [RefCell>; PerCpu::MAX_CPU_NUM as usize] = + [const { RefCell::new(None) }; PerCpu::MAX_CPU_NUM as usize]; #[inline(always)] pub(super) fn current_xapic_instance() -> &'static RefCell> { - unsafe { &XAPIC_INSTANCES.as_ref()[smp_get_processor_id() as usize] } + unsafe { &XAPIC_INSTANCES.as_ref()[smp_get_processor_id().data() as usize] } } /// TODO:统一变量 @@ -300,8 +300,8 @@ impl LocalAPIC for XApic { } /// 获取ID - fn id(&self) -> u32 { - unsafe { self.read(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_ID.into()) >> 24 } + fn id(&self) -> ApicId { + unsafe { ApicId::new(self.read(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_ID.into()) >> 24) } } /// 设置LVT寄存器的值 diff --git a/kernel/src/arch/x86_64/driver/c_adapter.rs b/kernel/src/arch/x86_64/driver/c_adapter.rs deleted file mode 100644 index dc47630e..00000000 --- a/kernel/src/arch/x86_64/driver/c_adapter.rs +++ /dev/null @@ -1,6 +0,0 @@ -use super::hpet::hpet_instance; - -#[no_mangle] -unsafe extern "C" fn rs_handle_hpet_irq(timer_num: u32) { - hpet_instance().handle_irq(timer_num); -} diff --git a/kernel/src/arch/x86_64/driver/hpet.c b/kernel/src/arch/x86_64/driver/hpet.c deleted file mode 100644 index 8eeb6407..00000000 --- a/kernel/src/arch/x86_64/driver/hpet.c +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include -#include - -extern void rs_handle_hpet_irq(uint32_t timer_num); - -hardware_intr_controller HPET_intr_controller = - { - .enable = apic_ioapic_enable, - .disable = apic_ioapic_disable, - .install = apic_ioapic_install, - .uninstall = apic_ioapic_uninstall, - .ack = apic_ioapic_edge_ack, -}; - -void HPET_handler(uint64_t number, uint64_t param, struct pt_regs *regs) -{ - rs_handle_hpet_irq(param); -} - -void c_hpet_register_irq() -{ - struct apic_IO_APIC_RTE_entry entry; - apic_make_rte_entry(&entry, 34, IO_APIC_FIXED, DEST_PHYSICAL, IDLE, POLARITY_HIGH, IRR_RESET, EDGE_TRIGGER, MASKED, 0); - irq_register(34, &entry, &HPET_handler, 0, &HPET_intr_controller, "HPET0"); -} diff --git a/kernel/src/arch/x86_64/driver/hpet.rs b/kernel/src/arch/x86_64/driver/hpet.rs index 5ceda536..6df59297 100644 --- a/kernel/src/arch/x86_64/driver/hpet.rs +++ b/kernel/src/arch/x86_64/driver/hpet.rs @@ -1,5 +1,4 @@ use core::{ - ffi::c_void, intrinsics::unlikely, mem::size_of, ptr::NonNull, @@ -7,6 +6,7 @@ use core::{ }; use acpi::HpetInfo; +use alloc::{string::ToString, sync::Arc}; use system_error::SystemError; use crate::{ @@ -16,8 +16,11 @@ use crate::{ timers::hpet::{HpetRegisters, HpetTimerRegisters}, }, exception::{ + irqdata::IrqHandlerData, + irqdesc::{IrqHandleFlags, IrqHandler, IrqReturn}, + manage::irq_manager, softirq::{softirq_vectors, SoftirqNumber}, - InterruptArch, + InterruptArch, IrqNumber, }, kdebug, kerror, kinfo, libs::{ @@ -31,10 +34,6 @@ use crate::{ time::timer::{clock, timer_get_first_expire, update_timer_jiffies}, }; -extern "C" { - fn c_hpet_register_irq() -> c_void; -} - static mut HPET_INSTANCE: Option = None; #[inline(always)] @@ -58,6 +57,8 @@ impl Hpet { /// HPET0 中断间隔为 10ms pub const HPET0_INTERVAL_USEC: u64 = 10000; + const HPET0_IRQ: IrqNumber = IrqNumber::new(34); + fn new(mut hpet_info: HpetInfo) -> Result { let paddr = PhysAddr::new(hpet_info.base_address); let map_size = size_of::(); @@ -107,6 +108,8 @@ impl Hpet { /// 使能HPET pub fn hpet_enable(&self) -> Result<(), SystemError> { + let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; + // !!!这里是临时糊代码的,需要在apic重构的时候修改!!! let (inner_guard, regs) = unsafe { self.hpet_regs_mut() }; let freq = regs.frequency(); @@ -135,8 +138,14 @@ impl Hpet { } drop(inner_guard); - // todo!("register irq in C"); - unsafe { c_hpet_register_irq() }; + irq_manager().request_irq( + Self::HPET0_IRQ, + "HPET0".to_string(), + &HpetIrqHandler, + IrqHandleFlags::IRQF_TRIGGER_RISING, + None, + )?; + self.enabled.store(true, Ordering::SeqCst); let (inner_guard, regs) = unsafe { self.hpet_regs_mut() }; @@ -147,6 +156,8 @@ impl Hpet { drop(inner_guard); kinfo!("HPET enabled"); + + drop(irq_guard); return Ok(()); } @@ -251,3 +262,18 @@ pub fn hpet_init() -> Result<(), SystemError> { return Ok(()); } + +#[derive(Debug)] +struct HpetIrqHandler; + +impl IrqHandler for HpetIrqHandler { + fn handle( + &self, + _irq: IrqNumber, + _static_data: Option<&dyn IrqHandlerData>, + _dynamic_data: Option>, + ) -> Result { + hpet_instance().handle_irq(0); + return Ok(IrqReturn::Handled); + } +} diff --git a/kernel/src/arch/x86_64/driver/mod.rs b/kernel/src/arch/x86_64/driver/mod.rs index 076387a4..cebddb96 100644 --- a/kernel/src/arch/x86_64/driver/mod.rs +++ b/kernel/src/arch/x86_64/driver/mod.rs @@ -1,5 +1,4 @@ pub mod apic; -mod c_adapter; pub mod hpet; pub mod tsc; pub mod video; diff --git a/kernel/src/arch/x86_64/include/x86_64_ipi.h b/kernel/src/arch/x86_64/include/x86_64_ipi.h deleted file mode 100644 index f3a499f5..00000000 --- a/kernel/src/arch/x86_64/include/x86_64_ipi.h +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @file ipi.h - * @author fslongjin(longjin@RinGoTek.cn) - * @brief 多核通信驱动 - * @version 0.1 - * @date 2022-04-07 - * - * @copyright Copyright (c) 2022 - * - */ - -#pragma once - -#include -#include - -/** - * @brief ipi中断处理注册函数 - * - * @param irq_num 中断向量号 - * @param arg 参数 - * @param handler 处理函数 - * @param param 参数 - * @param controller 当前为NULL - * @param irq_name ipi中断名 - * @return int 成功:0 - */ -int ipi_regiserIPI(uint64_t irq_num, void *arg, - void (*handler)(uint64_t irq_num, uint64_t param, struct pt_regs *regs), - uint64_t param, hardware_intr_controller *controller, char *irq_name); \ No newline at end of file diff --git a/kernel/src/arch/x86_64/interrupt/c_adapter.rs b/kernel/src/arch/x86_64/interrupt/c_adapter.rs index 87b0e7b5..461b41b3 100644 --- a/kernel/src/arch/x86_64/interrupt/c_adapter.rs +++ b/kernel/src/arch/x86_64/interrupt/c_adapter.rs @@ -1,3 +1,5 @@ +use crate::smp::cpu::ProcessorId; + use super::ipi::{ipi_send_smp_init, ipi_send_smp_startup}; #[no_mangle] @@ -9,7 +11,7 @@ unsafe extern "C" fn rs_ipi_send_smp_init() -> i32 { #[no_mangle] unsafe extern "C" fn rs_ipi_send_smp_startup(target_cpu: u32) -> i32 { - return ipi_send_smp_startup(target_cpu) + return ipi_send_smp_startup(ProcessorId::new(target_cpu)) .map(|_| 0) .unwrap_or_else(|e| e.to_posix_errno()); } diff --git a/kernel/src/arch/x86_64/interrupt/entry.rs b/kernel/src/arch/x86_64/interrupt/entry.rs index 69ef92ca..da092192 100644 --- a/kernel/src/arch/x86_64/interrupt/entry.rs +++ b/kernel/src/arch/x86_64/interrupt/entry.rs @@ -57,7 +57,8 @@ macro_rules! interrupt_handler { lea rax, ret_from_intr[rip] push rax mov rsi, {irqnum} - jmp do_IRQ + jmp x86_64_do_irq + // jmp do_IRQ " ), irqnum = const($name), @@ -294,7 +295,7 @@ interrupt_handler!(254); interrupt_handler!(255); #[inline(never)] -pub(super) unsafe fn setup_interrupt_gate() { +pub unsafe fn arch_setup_interrupt_gate() { set_intr_gate(32, 0, VirtAddr::new(irq_handler32 as usize)); set_intr_gate(33, 0, VirtAddr::new(irq_handler33 as usize)); set_intr_gate(34, 0, VirtAddr::new(irq_handler34 as usize)); diff --git a/kernel/src/arch/x86_64/interrupt/handle.rs b/kernel/src/arch/x86_64/interrupt/handle.rs new file mode 100644 index 00000000..02050fea --- /dev/null +++ b/kernel/src/arch/x86_64/interrupt/handle.rs @@ -0,0 +1,54 @@ +use core::intrinsics::likely; + +use crate::{ + arch::{ + driver::apic::{apic_timer::APIC_TIMER_IRQ_NUM, CurrentApic, LocalAPIC}, + sched::sched, + }, + exception::{irqdesc::irq_desc_manager, softirq::do_softirq, IrqNumber}, + process::{ + process::{current_pcb_flags, current_pcb_preempt_count}, + ProcessFlags, + }, +}; + +use super::TrapFrame; + +#[no_mangle] +unsafe extern "C" fn x86_64_do_irq(trap_frame: &mut TrapFrame, vector: u32) { + // swapgs + + if trap_frame.from_user() { + x86_64::registers::segmentation::GS::swap(); + // 拒绝用户态中断 + return; + } + + // 由于x86上面,虚拟中断号与物理中断号是一一对应的,所以这里直接使用vector作为中断号来查询irqdesc + + let desc = irq_desc_manager().lookup(IrqNumber::new(vector)); + + if likely(desc.is_some()) { + let desc = desc.unwrap(); + let handler = desc.handler(); + if likely(handler.is_some()) { + handler.unwrap().handle(&desc, trap_frame); + } else { + CurrentApic.send_eoi(); + } + } else { + CurrentApic.send_eoi(); + } + + do_softirq(); + + if current_pcb_preempt_count() > 0 { + return; + } + // 检测当前进程是否可被调度 + if (current_pcb_flags().contains(ProcessFlags::NEED_SCHEDULE)) + && vector == APIC_TIMER_IRQ_NUM.data() + { + sched(); + } +} diff --git a/kernel/src/arch/x86_64/interrupt/ipi.rs b/kernel/src/arch/x86_64/interrupt/ipi.rs index 275cdf96..3995171c 100644 --- a/kernel/src/arch/x86_64/interrupt/ipi.rs +++ b/kernel/src/arch/x86_64/interrupt/ipi.rs @@ -1,20 +1,33 @@ +use alloc::sync::Arc; use system_error::SystemError; use x86::apic::ApicId; use crate::{ arch::{ - driver::apic::{CurrentApic, LocalAPIC}, + driver::apic::{lapic_vector::local_apic_chip, CurrentApic, LocalAPIC}, smp::SMP_BOOT_DATA, }, - exception::ipi::{IpiKind, IpiTarget}, + exception::{ + ipi::{FlushTLBIpiHandler, IpiKind, IpiTarget, KickCpuIpiHandler}, + irqdata::{IrqData, IrqLineStatus}, + irqdesc::{irq_desc_manager, IrqDesc, IrqFlowHandler, IrqHandler}, + HardwareIrqNumber, IrqNumber, + }, + kerror, + smp::cpu::ProcessorId, }; +use super::TrapFrame; + +pub const IPI_NUM_KICK_CPU: IrqNumber = IrqNumber::new(200); +pub const IPI_NUM_FLUSH_TLB: IrqNumber = IrqNumber::new(201); /// IPI的种类(架构相关,指定了向量号) #[derive(Debug, Copy, Clone, Eq, PartialEq)] -#[repr(u8)] +#[repr(u32)] pub enum ArchIpiKind { - KickCpu = 200, - FlushTLB = 201, + KickCpu = IPI_NUM_KICK_CPU.data(), + FlushTLB = IPI_NUM_FLUSH_TLB.data(), + SpecVector(HardwareIrqNumber), } impl From for ArchIpiKind { @@ -22,6 +35,17 @@ impl From for ArchIpiKind { match kind { IpiKind::KickCpu => ArchIpiKind::KickCpu, IpiKind::FlushTLB => ArchIpiKind::FlushTLB, + IpiKind::SpecVector(vec) => ArchIpiKind::SpecVector(vec), + } + } +} + +impl Into for ArchIpiKind { + fn into(self) -> u8 { + match self { + ArchIpiKind::KickCpu => IPI_NUM_KICK_CPU.data() as u8, + ArchIpiKind::FlushTLB => IPI_NUM_FLUSH_TLB.data() as u8, + ArchIpiKind::SpecVector(vec) => (vec.data() & 0xFF) as u8, } } } @@ -46,7 +70,7 @@ impl From for ArchIpiTarget { IpiTarget::All => ArchIpiTarget::All, IpiTarget::Other => ArchIpiTarget::Other, IpiTarget::Specified(cpu_id) => { - ArchIpiTarget::Specified(Self::cpu_id_to_apic_id(cpu_id as u32)) + ArchIpiTarget::Specified(Self::cpu_id_to_apic_id(cpu_id)) } } } @@ -78,11 +102,11 @@ impl ArchIpiTarget { } #[inline(always)] - fn cpu_id_to_apic_id(cpu_id: u32) -> x86::apic::ApicId { + fn cpu_id_to_apic_id(cpu_id: ProcessorId) -> x86::apic::ApicId { if CurrentApic.x2apic_enabled() { - x86::apic::ApicId::X2Apic(cpu_id as u32) + x86::apic::ApicId::X2Apic(cpu_id.data() as u32) } else { - x86::apic::ApicId::XApic(cpu_id as u8) + x86::apic::ApicId::XApic(cpu_id.data() as u8) } } } @@ -102,7 +126,7 @@ impl Into for ArchIpiTarget { pub fn send_ipi(kind: IpiKind, target: IpiTarget) { // kdebug!("send_ipi: {:?} {:?}", kind, target); - let ipi_vec = ArchIpiKind::from(kind) as u8; + let ipi_vec = ArchIpiKind::from(kind).into(); let target = ArchIpiTarget::from(target); let shorthand: x86::apic::DestinationShorthand = target.into(); let destination: x86::apic::ApicId = target.into(); @@ -170,11 +194,11 @@ pub fn ipi_send_smp_init() -> Result<(), SystemError> { /// ## 参数 /// /// * `target_cpu` - 目标CPU -pub fn ipi_send_smp_startup(target_cpu: u32) -> Result<(), SystemError> { - if target_cpu as usize >= SMP_BOOT_DATA.cpu_count() { +pub fn ipi_send_smp_startup(target_cpu: ProcessorId) -> Result<(), SystemError> { + if target_cpu.data() as usize >= SMP_BOOT_DATA.cpu_count() { return Err(SystemError::EINVAL); } - let target: ArchIpiTarget = IpiTarget::Specified(target_cpu as usize).into(); + let target: ArchIpiTarget = IpiTarget::Specified(target_cpu).into(); let icr = if CurrentApic.x2apic_enabled() { x86::apic::Icr::for_x2apic( @@ -203,3 +227,42 @@ pub fn ipi_send_smp_startup(target_cpu: u32) -> Result<(), SystemError> { CurrentApic.write_icr(icr); return Ok(()); } + +/// 初始化IPI处理函数 +pub fn arch_ipi_handler_init() { + do_init_irq_handler(IPI_NUM_KICK_CPU); + do_init_irq_handler(IPI_NUM_FLUSH_TLB); +} + +fn do_init_irq_handler(irq: IrqNumber) { + let desc = irq_desc_manager().lookup(irq).unwrap(); + let irq_data: Arc = desc.irq_data(); + let mut chip_info_guard = irq_data.chip_info_write_irqsave(); + chip_info_guard.set_chip(Some(local_apic_chip().clone())); + + desc.modify_status(IrqLineStatus::IRQ_LEVEL, IrqLineStatus::empty()); + drop(chip_info_guard); + desc.set_handler(&X86_64IpiIrqFlowHandler); +} + +#[derive(Debug)] +struct X86_64IpiIrqFlowHandler; + +impl IrqFlowHandler for X86_64IpiIrqFlowHandler { + fn handle(&self, irq_desc: &Arc, _trap_frame: &mut TrapFrame) { + let irq = irq_desc.irq_data().irq(); + match irq { + IPI_NUM_KICK_CPU => { + KickCpuIpiHandler.handle(irq, None, None).ok(); + } + IPI_NUM_FLUSH_TLB => { + FlushTLBIpiHandler.handle(irq, None, None).ok(); + } + _ => { + kerror!("Unknown IPI: {}", irq.data()); + } + } + + CurrentApic.send_eoi(); + } +} diff --git a/kernel/src/arch/x86_64/interrupt/mod.rs b/kernel/src/arch/x86_64/interrupt/mod.rs index db36c1d9..69334718 100644 --- a/kernel/src/arch/x86_64/interrupt/mod.rs +++ b/kernel/src/arch/x86_64/interrupt/mod.rs @@ -1,6 +1,8 @@ mod c_adapter; pub(super) mod entry; +mod handle; pub mod ipi; +pub mod msi; pub mod trap; use core::{ @@ -16,11 +18,9 @@ use crate::{ kerror, }; -use self::entry::setup_interrupt_gate; - use super::{ asm::irqflags::{local_irq_restore, local_irq_save}, - driver::apic::{CurrentApic, LocalAPIC}, + driver::apic::{lapic_vector::arch_early_irq_init, CurrentApic, LocalAPIC}, }; /// @brief 关闭中断 @@ -45,8 +45,7 @@ impl InterruptArch for X86_64InterruptArch { #[inline(never)] unsafe fn arch_irq_init() -> Result<(), SystemError> { CurrentIrqArch::interrupt_disable(); - setup_interrupt_gate(); - CurrentApic.init_current_cpu(); + return Ok(()); } unsafe fn interrupt_enable() { @@ -90,6 +89,10 @@ impl InterruptArch for X86_64InterruptArch { kerror!("Unexpected IRQ trap at vector {}", irq.data()); CurrentApic.send_eoi(); } + + fn arch_early_irq_init() -> Result<(), SystemError> { + arch_early_irq_init() + } } /// 中断栈帧结构体 diff --git a/kernel/src/arch/x86_64/interrupt/msi.rs b/kernel/src/arch/x86_64/interrupt/msi.rs new file mode 100644 index 00000000..34d6c420 --- /dev/null +++ b/kernel/src/arch/x86_64/interrupt/msi.rs @@ -0,0 +1,89 @@ +use bitfield_struct::bitfield; + +#[allow(dead_code)] +#[derive(Debug)] +pub enum X86MsiData { + Normal(X86MsiDataNormal), + Dmar(X86MsiDataDmar), +} + +#[bitfield(u32)] +pub struct X86MsiDataNormal { + #[bits(8)] + pub vector: u8, + #[bits(3)] + pub delivery_mode: u8, + #[bits(1)] + pub dest_mode_logical: bool, + #[bits(2)] + reserved: u8, + #[bits(1)] + pub active_low: bool, + #[bits(1)] + pub is_level_triggered: bool, + #[bits(16)] + reserved2: u16, +} + +#[derive(Debug)] +pub struct X86MsiDataDmar { + pub dmar_subhandle: u32, +} + +impl X86MsiDataDmar { + #[allow(dead_code)] + pub const fn new(dmar_subhandle: u32) -> Self { + X86MsiDataDmar { dmar_subhandle } + } +} + +pub const X86_MSI_BASE_ADDRESS_LOW: u32 = 0xfee00000 >> 20; + +#[allow(dead_code)] +#[derive(Debug)] +pub enum X86MsiAddrLo { + Normal(X86MsiAddrLoNormal), + Dmar(X86MsiAddrLoDmar), +} + +#[bitfield(u32)] +pub struct X86MsiAddrLoNormal { + #[bits(2)] + reserved_0: u32, + #[bits(1)] + pub dest_mode_logical: bool, + #[bits(1)] + pub redirecti_hint: bool, + #[bits(1)] + reserved_1: bool, + #[bits(7)] + pub virt_destid_8_14: u32, + #[bits(8)] + pub destid_0_7: u32, + #[bits(12)] + pub base_address: u32, +} + +#[bitfield(u32)] +pub struct X86MsiAddrLoDmar { + #[bits(2)] + reserved_0: u32, + #[bits(1)] + pub index_15: bool, + #[bits(1)] + pub subhandle_valid: bool, + #[bits(1)] + pub format: bool, + #[bits(15)] + pub index_0_14: u32, + #[bits(12)] + pub base_address: u32, +} + +#[bitfield(u32)] +pub struct X86MsiAddrHi { + #[bits(8)] + reserved: u32, + #[bits(24)] + pub destid_8_31: u32, +} diff --git a/kernel/src/arch/x86_64/interrupt/trap.rs b/kernel/src/arch/x86_64/interrupt/trap.rs index 8d567b78..1305c221 100644 --- a/kernel/src/arch/x86_64/interrupt/trap.rs +++ b/kernel/src/arch/x86_64/interrupt/trap.rs @@ -73,7 +73,7 @@ unsafe extern "C" fn do_divide_error(regs: &'static TrapFrame, error_code: u64) error_code, regs.rsp, regs.rip, - smp_get_processor_id(), + smp_get_processor_id().data(), ProcessManager::current_pid() ); panic!("Divide Error"); @@ -87,7 +87,7 @@ unsafe extern "C" fn do_debug(regs: &'static TrapFrame, error_code: u64) { error_code, regs.rsp, regs.rip, - smp_get_processor_id(), + smp_get_processor_id().data(), ProcessManager::current_pid() ); panic!("Debug Exception"); @@ -101,7 +101,7 @@ unsafe extern "C" fn do_nmi(regs: &'static TrapFrame, error_code: u64) { error_code, regs.rsp, regs.rip, - smp_get_processor_id(), + smp_get_processor_id().data(), ProcessManager::current_pid() ); panic!("NMI Interrupt"); @@ -115,7 +115,7 @@ unsafe extern "C" fn do_int3(regs: &'static TrapFrame, error_code: u64) { error_code, regs.rsp, regs.rip, - smp_get_processor_id(), + smp_get_processor_id().data(), ProcessManager::current_pid() ); panic!("Int3"); @@ -129,7 +129,7 @@ unsafe extern "C" fn do_overflow(regs: &'static TrapFrame, error_code: u64) { error_code, regs.rsp, regs.rip, - smp_get_processor_id(), + smp_get_processor_id().data(), ProcessManager::current_pid() ); panic!("Overflow Exception"); @@ -143,7 +143,7 @@ unsafe extern "C" fn do_bounds(regs: &'static TrapFrame, error_code: u64) { error_code, regs.rsp, regs.rip, - smp_get_processor_id(), + smp_get_processor_id().data(), ProcessManager::current_pid() ); panic!("Bounds Check"); @@ -157,7 +157,7 @@ unsafe extern "C" fn do_undefined_opcode(regs: &'static TrapFrame, error_code: u error_code, regs.rsp, regs.rip, - smp_get_processor_id(), + smp_get_processor_id().data(), ProcessManager::current_pid() ); panic!("Undefined Opcode"); @@ -171,7 +171,7 @@ unsafe extern "C" fn do_dev_not_avaliable(regs: &'static TrapFrame, error_code: error_code, regs.rsp, regs.rip, - smp_get_processor_id(), + smp_get_processor_id().data(), ProcessManager::current_pid() ); panic!("Device Not Available"); @@ -185,7 +185,7 @@ unsafe extern "C" fn do_double_fault(regs: &'static TrapFrame, error_code: u64) error_code, regs.rsp, regs.rip, - smp_get_processor_id(), + smp_get_processor_id().data(), ProcessManager::current_pid() ); panic!("Double Fault"); @@ -199,7 +199,7 @@ unsafe extern "C" fn do_coprocessor_segment_overrun(regs: &'static TrapFrame, er error_code, regs.rsp, regs.rip, - smp_get_processor_id(), + smp_get_processor_id().data(), ProcessManager::current_pid() ); panic!("Coprocessor Segment Overrun"); @@ -236,7 +236,7 @@ unsafe extern "C" fn do_invalid_TSS(regs: &'static TrapFrame, error_code: u64) { error_code, regs.rsp, regs.rip, - smp_get_processor_id(), + smp_get_processor_id().data(), ProcessManager::current_pid(), msg1, msg2 @@ -252,7 +252,7 @@ unsafe extern "C" fn do_segment_not_exists(regs: &'static TrapFrame, error_code: error_code, regs.rsp, regs.rip, - smp_get_processor_id(), + smp_get_processor_id().data(), ProcessManager::current_pid() ); panic!("Segment Not Exists"); @@ -266,7 +266,7 @@ unsafe extern "C" fn do_stack_segment_fault(regs: &'static TrapFrame, error_code error_code, regs.rsp, regs.rip, - smp_get_processor_id(), + smp_get_processor_id().data(), ProcessManager::current_pid() ); panic!("Stack Segment Fault"); @@ -313,7 +313,7 @@ Segment Selector Index: {:#x}\n error_code, regs.rsp, regs.rip, - smp_get_processor_id(), + smp_get_processor_id().data(), ProcessManager::current_pid(), msg1, msg2, msg3, error_code & 0xfff8 @@ -329,7 +329,7 @@ unsafe extern "C" fn do_page_fault(regs: &'static TrapFrame, error_code: u64) { error_code, regs.rsp, regs.rip, - smp_get_processor_id(), + smp_get_processor_id().data(), ProcessManager::current_pid(), x86::controlregs::cr2() ); @@ -370,7 +370,7 @@ unsafe extern "C" fn do_x87_FPU_error(regs: &'static TrapFrame, error_code: u64) error_code, regs.rsp, regs.rip, - smp_get_processor_id(), + smp_get_processor_id().data(), ProcessManager::current_pid() ); panic!("x87 FPU Error"); @@ -384,7 +384,7 @@ unsafe extern "C" fn do_alignment_check(regs: &'static TrapFrame, error_code: u6 error_code, regs.rsp, regs.rip, - smp_get_processor_id(), + smp_get_processor_id().data(), ProcessManager::current_pid() ); panic!("Alignment Check"); @@ -398,7 +398,7 @@ unsafe extern "C" fn do_machine_check(regs: &'static TrapFrame, error_code: u64) error_code, regs.rsp, regs.rip, - smp_get_processor_id(), + smp_get_processor_id().data(), ProcessManager::current_pid() ); panic!("Machine Check"); @@ -412,7 +412,7 @@ unsafe extern "C" fn do_SIMD_exception(regs: &'static TrapFrame, error_code: u64 error_code, regs.rsp, regs.rip, - smp_get_processor_id(), + smp_get_processor_id().data(), ProcessManager::current_pid() ); panic!("SIMD Exception"); @@ -426,7 +426,7 @@ unsafe extern "C" fn do_virtualization_exception(regs: &'static TrapFrame, error error_code, regs.rsp, regs.rip, - smp_get_processor_id(), + smp_get_processor_id().data(), ProcessManager::current_pid() ); panic!("Virtualization Exception"); diff --git a/kernel/src/arch/x86_64/interrupt/x86_64_ipi.c b/kernel/src/arch/x86_64/interrupt/x86_64_ipi.c deleted file mode 100644 index f73f929c..00000000 --- a/kernel/src/arch/x86_64/interrupt/x86_64_ipi.c +++ /dev/null @@ -1,15 +0,0 @@ -#include "x86_64_ipi.h" -#include - -int ipi_regiserIPI(uint64_t irq_num, void *arg, - void (*handler)(uint64_t irq_num, uint64_t param, struct pt_regs *regs), - uint64_t param, hardware_intr_controller *controller, char *irq_name) -{ - irq_desc_t *p = &SMP_IPI_desc[irq_num - 200]; - p->controller = NULL; // 由于ipi不涉及到具体的硬件操作,因此不需要controller - p->irq_name = irq_name; - p->parameter = param; - p->flags = 0; - p->handler = handler; - return 0; -} \ No newline at end of file diff --git a/kernel/src/arch/x86_64/kvm/vmx/ept.rs b/kernel/src/arch/x86_64/kvm/vmx/ept.rs index b6b744a3..6694448d 100644 --- a/kernel/src/arch/x86_64/kvm/vmx/ept.rs +++ b/kernel/src/arch/x86_64/kvm/vmx/ept.rs @@ -4,6 +4,8 @@ use crate::arch::MMArch; use crate::mm::page::PageFlags; use crate::mm::{PageTableKind, PhysAddr, VirtAddr}; use crate::smp::core::smp_get_processor_id; +use crate::smp::cpu::AtomicProcessorId; +use crate::smp::cpu::ProcessorId; use core::sync::atomic::{compiler_fence, AtomicUsize, Ordering}; use system_error::SystemError; use x86::msr; @@ -25,9 +27,9 @@ pub fn check_ept_features() -> Result<(), SystemError> { /// 标志当前没有处理器持有内核映射器的锁 /// 之所以需要这个标志,是因为AtomicUsize::new(0)会把0当作一个处理器的id -const EPT_MAPPER_NO_PROCESSOR: usize = !0; +const EPT_MAPPER_NO_PROCESSOR: ProcessorId = ProcessorId::INVALID; /// 当前持有内核映射器锁的处理器 -static EPT_MAPPER_LOCK_OWNER: AtomicUsize = AtomicUsize::new(EPT_MAPPER_NO_PROCESSOR); +static EPT_MAPPER_LOCK_OWNER: AtomicProcessorId = AtomicProcessorId::new(EPT_MAPPER_NO_PROCESSOR); /// 内核映射器的锁计数器 static EPT_MAPPER_LOCK_COUNT: AtomicUsize = AtomicUsize::new(0); @@ -41,7 +43,7 @@ pub struct EptMapper { } impl EptMapper { - fn lock_cpu(cpuid: usize, mapper: PageMapper) -> Self { + fn lock_cpu(cpuid: ProcessorId, mapper: PageMapper) -> Self { loop { match EPT_MAPPER_LOCK_OWNER.compare_exchange_weak( EPT_MAPPER_NO_PROCESSOR, @@ -69,7 +71,7 @@ impl EptMapper { /// @brief 锁定内核映射器, 并返回一个内核映射器对象 #[inline(always)] pub fn lock() -> Self { - let cpuid = smp_get_processor_id() as usize; + let cpuid = smp_get_processor_id(); let mapper = unsafe { PageMapper::current(PageTableKind::EPT, LockedFrameAllocator) }; return Self::lock_cpu(cpuid, mapper); } diff --git a/kernel/src/arch/x86_64/process/table.rs b/kernel/src/arch/x86_64/process/table.rs index bf5aa716..75380170 100644 --- a/kernel/src/arch/x86_64/process/table.rs +++ b/kernel/src/arch/x86_64/process/table.rs @@ -32,24 +32,24 @@ pub unsafe fn switch_fs_and_gs(fs: SegmentSelector, gs: SegmentSelector) { #[derive(Debug)] pub struct TSSManager { - tss: [TaskStateSegment; PerCpu::MAX_CPU_NUM], + tss: [TaskStateSegment; PerCpu::MAX_CPU_NUM as usize], } impl TSSManager { const fn new() -> Self { return Self { - tss: [TaskStateSegment::new(); PerCpu::MAX_CPU_NUM], + tss: [TaskStateSegment::new(); PerCpu::MAX_CPU_NUM as usize], }; } /// 获取当前CPU的TSS pub unsafe fn current_tss() -> &'static mut TaskStateSegment { - &mut TSS_MANAGER.tss[smp_get_processor_id() as usize] + &mut TSS_MANAGER.tss[smp_get_processor_id().data() as usize] } /// 加载当前CPU的TSS pub unsafe fn load_tr() { - let index = (10 + smp_get_processor_id() * 2) as u16; + let index = (10 + smp_get_processor_id().data() * 2) as u16; let selector = SegmentSelector::new(index, Ring::Ring0); Self::set_tss_descriptor( diff --git a/kernel/src/arch/x86_64/sched.rs b/kernel/src/arch/x86_64/sched.rs index db4e7197..0a49e9e6 100644 --- a/kernel/src/arch/x86_64/sched.rs +++ b/kernel/src/arch/x86_64/sched.rs @@ -1,9 +1,11 @@ +use core::hint::spin_loop; + use crate::{ exception::InterruptArch, include::bindings::bindings::enter_syscall_int, sched::SchedArch, - syscall::SYS_SCHED, + smp::core::smp_get_processor_id, syscall::SYS_SCHED, }; -use super::CurrentIrqArch; +use super::{driver::apic::apic_timer::apic_timer_init, CurrentIrqArch}; /// @brief 若内核代码不处在中断上下文中,那么将可以使用本函数,发起一个sys_sched系统调用,然后运行调度器。 /// 由于只能在中断上下文中进行进程切换,因此需要发起一个系统调用SYS_SCHED。 @@ -14,9 +16,7 @@ pub extern "C" fn sched() { } } -extern "C" { - fn apic_timer_init(); -} +static mut BSP_INIT_OK: bool = false; pub struct X86_64SchedArch; @@ -33,8 +33,23 @@ impl SchedArch for X86_64SchedArch { } fn initial_setup_sched_local() { - unsafe { - apic_timer_init(); + let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; + + let cpu_id = smp_get_processor_id(); + + if cpu_id.data() != 0 { + while !unsafe { BSP_INIT_OK } { + spin_loop(); + } } + + apic_timer_init(); + if smp_get_processor_id().data() == 0 { + unsafe { + BSP_INIT_OK = true; + } + } + + drop(irq_guard); } } diff --git a/kernel/src/arch/x86_64/smp/mod.rs b/kernel/src/arch/x86_64/smp/mod.rs index c9dbc88c..15630f5e 100644 --- a/kernel/src/arch/x86_64/smp/mod.rs +++ b/kernel/src/arch/x86_64/smp/mod.rs @@ -15,7 +15,7 @@ use crate::{ libs::rwlock::RwLock, mm::percpu::PerCpu, process::ProcessManager, - smp::{core::smp_get_processor_id, SMPArch}, + smp::{core::smp_get_processor_id, cpu::ProcessorId, SMPArch}, }; use super::{acpi::early_acpi_boot_init, CurrentIrqArch}; @@ -35,7 +35,7 @@ struct ApStartStackInfo { #[no_mangle] unsafe extern "C" fn smp_ap_start() -> ! { CurrentIrqArch::interrupt_disable(); - let vaddr = cpu_core_info[smp_get_processor_id() as usize].stack_start as usize; + let vaddr = cpu_core_info[smp_get_processor_id().data() as usize].stack_start as usize; compiler_fence(core::sync::atomic::Ordering::SeqCst); let v = ApStartStackInfo { vaddr }; smp_init_switch_stack(&v); @@ -55,8 +55,8 @@ unsafe extern "sysv64" fn smp_init_switch_stack(st: &ApStartStackInfo) -> ! { unsafe extern "C" fn smp_ap_start_stage1() -> ! { let id = smp_get_processor_id(); - kdebug!("smp_ap_start_stage1: id: {}\n", id); - let current_idle = ProcessManager::idle_pcb()[smp_get_processor_id() as usize].clone(); + kdebug!("smp_ap_start_stage1: id: {}\n", id.data()); + let current_idle = ProcessManager::idle_pcb()[smp_get_processor_id().data() as usize].clone(); let tss = TSSManager::current_tss(); @@ -80,7 +80,7 @@ pub struct SmpBootData { /// CPU的物理ID(指的是Local APIC ID) /// /// 这里必须保证第0项的是bsp的物理ID - phys_id: [usize; PerCpu::MAX_CPU_NUM], + phys_id: [usize; PerCpu::MAX_CPU_NUM as usize], } #[allow(dead_code)] @@ -99,17 +99,17 @@ impl SmpBootData { self.phys_id[0] } - pub unsafe fn set_cpu_count(&self, cpu_count: usize) { + pub unsafe fn set_cpu_count(&self, cpu_count: u32) { if self.initialized.load(Ordering::SeqCst) == false { let p = self as *const SmpBootData as *mut SmpBootData; - (*p).cpu_count = cpu_count; + (*p).cpu_count = cpu_count.try_into().unwrap(); } } - pub unsafe fn set_phys_id(&self, cpu_id: usize, phys_id: usize) { + pub unsafe fn set_phys_id(&self, cpu_id: ProcessorId, phys_id: usize) { if self.initialized.load(Ordering::SeqCst) == false { let p = self as *const SmpBootData as *mut SmpBootData; - (*p).phys_id[cpu_id] = phys_id; + (*p).phys_id[cpu_id.data() as usize] = phys_id; } } @@ -122,19 +122,19 @@ impl SmpBootData { pub(super) static SMP_BOOT_DATA: SmpBootData = SmpBootData { initialized: AtomicBool::new(false), cpu_count: 0, - phys_id: [0; PerCpu::MAX_CPU_NUM], + phys_id: [0; PerCpu::MAX_CPU_NUM as usize], }; #[allow(dead_code)] #[derive(Debug)] pub struct X86_64SmpManager { - ia64_cpu_to_sapicid: RwLock<[Option; PerCpu::MAX_CPU_NUM]>, + ia64_cpu_to_sapicid: RwLock<[Option; PerCpu::MAX_CPU_NUM as usize]>, } impl X86_64SmpManager { pub const fn new() -> Self { return Self { - ia64_cpu_to_sapicid: RwLock::new([None; PerCpu::MAX_CPU_NUM]), + ia64_cpu_to_sapicid: RwLock::new([None; PerCpu::MAX_CPU_NUM as usize]), }; } /// initialize the logical cpu number to APIC ID mapping diff --git a/kernel/src/driver/Makefile b/kernel/src/driver/Makefile index f19e7f28..86899ed7 100644 --- a/kernel/src/driver/Makefile +++ b/kernel/src/driver/Makefile @@ -1,7 +1,7 @@ CFLAGS += -I . -kernel_driver_subdirs:=pci acpi disk keyboard mouse multiboot2 timers hid +kernel_driver_subdirs:=acpi disk multiboot2 timers hid ECHO: @echo "$@" diff --git a/kernel/src/driver/base/device/driver.rs b/kernel/src/driver/base/device/driver.rs index dc93ab2a..5c8c0384 100644 --- a/kernel/src/driver/base/device/driver.rs +++ b/kernel/src/driver/base/device/driver.rs @@ -50,7 +50,7 @@ pub fn driver_manager() -> &'static DriverManager { /// 否则在运行时会报错 pub trait Driver: Sync + Send + Debug + KObject { fn coredump(&self, _device: &Arc) -> Result<(), SystemError> { - Err(SystemError::EOPNOTSUPP_OR_ENOTSUP) + Err(SystemError::ENOSYS) } /// @brief: 获取驱动标识符 diff --git a/kernel/src/driver/base/device/mod.rs b/kernel/src/driver/base/device/mod.rs index 4f325a2c..76dfe479 100644 --- a/kernel/src/driver/base/device/mod.rs +++ b/kernel/src/driver/base/device/mod.rs @@ -9,6 +9,7 @@ use crate::{ acpi::glue::acpi_device_notify, base::map::{LockedDevsMap, LockedKObjMap}, }, + exception::irqdata::IrqHandlerData, filesystem::{ sysfs::{ file::sysfs_emit_str, sysfs_instance, Attribute, AttributeGroup, SysFSOps, @@ -875,7 +876,7 @@ impl DeviceMatcher<&str> for DeviceMatchName { } /// Cookie to identify the device -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Hash)] pub struct DeviceId { data: Option<&'static str>, allocated: Option, @@ -883,7 +884,7 @@ pub struct DeviceId { impl DeviceId { #[allow(dead_code)] - pub fn new(data: Option<&'static str>, allocated: Option) -> Option { + pub fn new(data: Option<&'static str>, allocated: Option) -> Option> { if data.is_none() && allocated.is_none() { return None; } @@ -893,7 +894,7 @@ impl DeviceId { return None; } - return Some(Self { data, allocated }); + return Some(Arc::new(Self { data, allocated })); } pub fn id(&self) -> Option<&str> { @@ -904,6 +905,7 @@ impl DeviceId { } } + #[allow(dead_code)] pub fn set_allocated(&mut self, allocated: String) { self.allocated = Some(allocated); self.data = None; @@ -915,3 +917,7 @@ impl PartialEq for DeviceId { return self.id() == other.id(); } } + +impl Eq for DeviceId {} + +impl IrqHandlerData for DeviceId {} diff --git a/kernel/src/driver/input/ps2_dev/mod.rs b/kernel/src/driver/input/ps2_dev/mod.rs index feedb874..07e4b6bd 100644 --- a/kernel/src/driver/input/ps2_dev/mod.rs +++ b/kernel/src/driver/input/ps2_dev/mod.rs @@ -1 +1,46 @@ +use bitfield_struct::bitfield; + pub mod ps2_device; + +/// PS2键盘控制器的状态寄存器 +#[bitfield(u8)] +pub struct Ps2StatusRegister { + /// 输出缓冲区满标志 + /// + /// (必须在尝试从 IO 端口 0x60 读取数据之前设置) + pub outbuf_full: bool, + + /// 输入缓冲区满标志 + /// + /// (在尝试向 IO 端口 0x60 或 IO 端口 0x64 写入数据之前必须清除) + pub inbuf_full: bool, + + /// 系统标志 + /// + /// 如果系统通过自检 (POST),则意味着在复位时被清除并由固件设置(通过 PS/2 控制器配置字节) + pub system_flag: bool, + + /// 命令/数据标志 + /// + /// (0 = 写入输入缓冲区的数据是 PS/2 设备的数据,1 = 写入输入缓冲区的数据是 PS/2 控制器命令的数据) + pub command_data: bool, + + /// 未知标志1 + /// + /// 可能是“键盘锁”(现代系统中更可能未使用) + pub unknown1: bool, + + /// 未知标志2 + /// + /// 可能是“接收超时”或“第二个 PS/2 端口输出缓冲区已满” + pub unknown2: bool, + /// 超时错误标志 + /// + /// 超时错误(0 = 无错误,1 = 超时错误) + pub timeout_error: bool, + + /// 奇偶校验错误标志 + /// + /// (0 = 无错误,1 = 奇偶校验错误) + pub parity_error: bool, +} diff --git a/kernel/src/driver/input/ps2_mouse/ps_mouse_device.rs b/kernel/src/driver/input/ps2_mouse/ps_mouse_device.rs index f0538b12..66f2c050 100644 --- a/kernel/src/driver/input/ps2_mouse/ps_mouse_device.rs +++ b/kernel/src/driver/input/ps2_mouse/ps_mouse_device.rs @@ -3,6 +3,7 @@ use core::hint::spin_loop; use alloc::{ string::ToString, sync::{Arc, Weak}, + vec::Vec, }; use kdepends::ringbuffer::{AllocRingBuffer, RingBuffer}; use system_error::SystemError; @@ -637,7 +638,7 @@ impl IndexNode for Ps2MouseDevice { self } - fn list(&self) -> Result, SystemError> { + fn list(&self) -> Result, SystemError> { todo!() } diff --git a/kernel/src/driver/input/ps2_mouse/ps_mouse_driver.rs b/kernel/src/driver/input/ps2_mouse/ps_mouse_driver.rs index 5138c62c..4321d2cb 100644 --- a/kernel/src/driver/input/ps2_mouse/ps_mouse_driver.rs +++ b/kernel/src/driver/input/ps2_mouse/ps_mouse_driver.rs @@ -10,7 +10,7 @@ use crate::{ arch::{io::PortIOArch, CurrentPortIOArch}, driver::{ base::{ - device::{bus::Bus, driver::Driver, Device, IdTable}, + device::{bus::Bus, driver::Driver, Device, DeviceId, IdTable}, kobject::{KObjType, KObject, KObjectState, LockedKObjectState}, kset::KSet, }, @@ -19,6 +19,12 @@ use crate::{ serio_driver::{serio_driver_manager, SerioDriver}, }, }, + exception::{ + irqdata::IrqHandlerData, + irqdesc::{IrqHandleFlags, IrqHandler, IrqReturn}, + manage::irq_manager, + IrqNumber, + }, filesystem::kernfs::KernFSInode, init::initcall::INITCALL_DEVICE, libs::{ @@ -29,18 +35,30 @@ use crate::{ use super::ps_mouse_device::{ps2_mouse_device, Ps2MouseDevice}; -extern "C" { - fn c_ps2_mouse_init(); -} +const PS2_MOUSE_IRQ_NUM: IrqNumber = IrqNumber::new(0x2c); #[no_mangle] -unsafe extern "C" fn ps2_mouse_driver_interrupt() { - if let Some(psmouse_device) = ps2_mouse_device() { - ps2_mouse_driver() - .interrupt(&(psmouse_device as Arc), 0, 0) - .ok(); - } else { - unsafe { CurrentPortIOArch::in8(0x60) }; +unsafe extern "C" fn ps2_mouse_driver_interrupt() {} + +#[derive(Debug)] +struct Ps2MouseIrqHandler; + +impl IrqHandler for Ps2MouseIrqHandler { + fn handle( + &self, + _irq: IrqNumber, + _static_data: Option<&dyn IrqHandlerData>, + _dev_id: Option>, + ) -> Result { + if let Some(psmouse_device) = ps2_mouse_device() { + return Ok(ps2_mouse_driver() + .interrupt(&(psmouse_device as Arc), 0, 0) + .map(|_| IrqReturn::Handled) + .unwrap_or_else(|_| IrqReturn::NotHandled)); + } else { + unsafe { CurrentPortIOArch::in8(0x60) }; + return Ok(IrqReturn::NotHandled); + } } } @@ -226,7 +244,13 @@ impl SerioDriver for Ps2MouseDriver { device.set_driver(Some(self.inner.lock_irqsave().self_ref.clone())); device.init()?; - unsafe { c_ps2_mouse_init() }; + irq_manager().request_irq( + PS2_MOUSE_IRQ_NUM, + "psmouse".to_string(), + &Ps2MouseIrqHandler, + IrqHandleFlags::IRQF_SHARED | IrqHandleFlags::IRQF_TRIGGER_RISING, + Some(DeviceId::new(Some(Self::NAME), None).unwrap()), + )?; return Ok(()); } diff --git a/kernel/src/driver/keyboard/Makefile b/kernel/src/driver/keyboard/Makefile deleted file mode 100644 index f8513471..00000000 --- a/kernel/src/driver/keyboard/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -SRC = $(wildcard *.c) -OBJ = $(SRC:.c=.o) -CFLAGS += -I . - -.PHONY: all - -all: $(OBJ) - -%.o: %.c - $(CC) $(CFLAGS) -c $< -o $@ \ No newline at end of file diff --git a/kernel/src/driver/keyboard/mod.rs b/kernel/src/driver/keyboard/mod.rs index b0239d9d..b3db5b27 100644 --- a/kernel/src/driver/keyboard/mod.rs +++ b/kernel/src/driver/keyboard/mod.rs @@ -1,24 +1 @@ -use crate::init::initcall::INITCALL_LATE; -use core::ffi::c_void; -use system_error::SystemError; -use unified_init::macros::unified_init; - pub mod ps2_keyboard; -// pub mod ps2_keyboard_inode; - -extern "C" { - fn ps2_keyboard_init() -> c_void; -} - -/// 初始化ps2键盘 -/// -/// todo: 将ps2键盘适配到设备驱动模型后,把初始化时机改为INITCALL_DEVICE -/// -/// 当前是LATE的原因是键盘驱动的TypeOneFSM需要在tty设备初始化之后才能工作。 -#[unified_init(INITCALL_LATE)] -fn rs_ps2_keyboard_init() -> Result<(), SystemError> { - unsafe { - ps2_keyboard_init(); - } - return Ok(()); -} diff --git a/kernel/src/driver/keyboard/ps2_keyboard.c b/kernel/src/driver/keyboard/ps2_keyboard.c deleted file mode 100644 index b045a58c..00000000 --- a/kernel/src/driver/keyboard/ps2_keyboard.c +++ /dev/null @@ -1,209 +0,0 @@ -#include "ps2_keyboard.h" -#include -#include -#include -#include -#include -#include -#include - -// 键盘输入缓冲区 -static struct kfifo_t kb_buf; - -extern void ps2_keyboard_register(struct vfs_file_operations_t *); -extern void ps2_keyboard_parse_keycode(uint8_t input); - -// 缓冲区读写锁 -static spinlock_t ps2_kb_buf_rw_lock; - -/** - * @brief 重置ps2键盘输入缓冲区 - * - * @param kbp 缓冲区对象指针 - */ -static void ps2_keyboard_reset_buffer(struct kfifo_t *kbp) -{ - kfifo_reset(kbp); -} -struct apic_IO_APIC_RTE_entry entry; - -hardware_intr_controller ps2_keyboard_intr_controller = - { - .enable = apic_ioapic_enable, - .disable = apic_ioapic_disable, - .install = apic_ioapic_install, - .uninstall = apic_ioapic_uninstall, - .ack = apic_ioapic_edge_ack, - -}; - -/** - * @brief 打开键盘文件 - * - * @param inode 所在的inode - * @param filp 文件指针 - * @return long - */ -long ps2_keyboard_open(void *inode, void *filp) -{ - ps2_keyboard_reset_buffer(&kb_buf); - return 0; -} - -/** - * @brief 关闭键盘文件 - * - * @param inode 所在的inode - * @param filp 文件指针 - * @return long - */ -long ps2_keyboard_close(void *inode, void *filp) -{ - ps2_keyboard_reset_buffer(&kb_buf); - return 0; -} - -/** - * @brief 键盘io控制接口 - * - * @param inode 所在的inode - * @param filp 键盘文件指针 - * @param cmd 命令 - * @param arg 参数 - * @return long - */ -long ps2_keyboard_ioctl(void *inode, void *filp, uint64_t cmd, uint64_t arg) -{ - switch (cmd) - { - case KEYBOARD_CMD_RESET_BUFFER: - ps2_keyboard_reset_buffer(&kb_buf); - break; - - default: - break; - } - return 0; -} - -/** - * @brief 读取键盘文件的操作接口 - * - * @param filp 文件指针 - * @param buf 输出缓冲区 - * @param count 要读取的字节数 - * @param position 读取的位置 - * @return long 读取的字节数 - */ -long ps2_keyboard_read(void *filp, char *buf, int64_t count, long *position) -{ - // 缓冲区为空则等待 - while (kfifo_empty(&kb_buf)) - ; - - count = (count > kb_buf.size) ? kb_buf.size : count; - return kfifo_out(&kb_buf, buf, count); -} - -/** - * @brief 键盘文件写入接口(无作用,空) - * - * @param filp - * @param buf - * @param count - * @param position - * @return long - */ -long ps2_keyboard_write(void *filp, char *buf, int64_t count, long *position) -{ - return 0; -} -/** - * @brief ps2键盘驱动的虚拟文件接口 - * - */ -struct vfs_file_operations_t ps2_keyboard_fops = - { - .open = ps2_keyboard_open, - .close = ps2_keyboard_close, - .ioctl = ps2_keyboard_ioctl, - .read = ps2_keyboard_read, - .write = ps2_keyboard_write, -}; - -/** - * @brief 键盘中断处理函数(中断上半部) - * 将数据存入缓冲区 - * @param irq_num 中断向量号 - * @param param 参数 - * @param regs 寄存器信息 - */ -void ps2_keyboard_handler(ul irq_num, ul buf_vaddr, struct pt_regs *regs) -{ - unsigned char x = io_in8(PORT_PS2_KEYBOARD_DATA); - ps2_keyboard_parse_keycode((uint8_t)x); -} -/** - * @brief 初始化键盘驱动程序的函数 - * - */ -void ps2_keyboard_init() -{ - - // ======= 初始化键盘循环队列缓冲区 =========== - - // 初始化键盘循环队列缓冲区 - kfifo_alloc(&kb_buf, ps2_keyboard_buffer_size, 0); - - // ======== 初始化中断RTE entry ========== - - entry.vector = PS2_KEYBOARD_INTR_VECTOR; // 设置中断向量号 - entry.deliver_mode = IO_APIC_FIXED; // 投递模式:混合 - entry.dest_mode = DEST_PHYSICAL; // 物理模式投递中断 - entry.deliver_status = IDLE; - entry.trigger_mode = EDGE_TRIGGER; // 设置边沿触发 - entry.polarity = POLARITY_HIGH; // 高电平触发 - entry.remote_IRR = IRR_RESET; - entry.mask = MASKED; - entry.reserved = 0; - - entry.destination.physical.reserved1 = 0; - entry.destination.physical.reserved2 = 0; - entry.destination.physical.phy_dest = 0; // 设置投递到BSP处理器 - - // ======== 初始化键盘控制器,写入配置值 ========= - wait_ps2_keyboard_write(); - io_out8(PORT_PS2_KEYBOARD_CONTROL, PS2_KEYBOARD_COMMAND_WRITE); - wait_ps2_keyboard_write(); - io_out8(PORT_PS2_KEYBOARD_DATA, PS2_KEYBOARD_PARAM_INIT); - wait_ps2_keyboard_write(); - - // 执行一百万次nop,等待键盘控制器把命令执行完毕 - for (int i = 0; i < 1000; ++i) - for (int j = 0; j < 1000; ++j) - nop(); - - - // 初始化键盘缓冲区的读写锁 - spin_init(&ps2_kb_buf_rw_lock); - - // 注册中断处理程序 - irq_register(PS2_KEYBOARD_INTR_VECTOR, &entry, &ps2_keyboard_handler, (ul)&kb_buf, &ps2_keyboard_intr_controller, "ps/2 keyboard"); - - // 先读一下键盘的数据,防止由于在键盘初始化之前,由于按键被按下从而导致接收不到中断。 - io_in8(PORT_PS2_KEYBOARD_DATA); - // 将设备挂载到devfs - ps2_keyboard_register(&ps2_keyboard_fops); - - kinfo("ps/2 keyboard registered."); -} - -/** - * @brief 键盘驱动卸载函数 - * - */ -void ps2_keyboard_exit() -{ - irq_unregister(PS2_KEYBOARD_INTR_VECTOR); - kfifo_free_alloc(&kb_buf); -} diff --git a/kernel/src/driver/keyboard/ps2_keyboard.h b/kernel/src/driver/keyboard/ps2_keyboard.h deleted file mode 100644 index 5a75e072..00000000 --- a/kernel/src/driver/keyboard/ps2_keyboard.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include - -#define PS2_KEYBOARD_INTR_VECTOR 0x21 // 键盘的中断向量号 - -// 定义键盘循环队列缓冲区大小为100bytes -#define ps2_keyboard_buffer_size 8 - -#define KEYBOARD_CMD_RESET_BUFFER 1 - -#define PORT_PS2_KEYBOARD_DATA 0x60 -#define PORT_PS2_KEYBOARD_STATUS 0x64 -#define PORT_PS2_KEYBOARD_CONTROL 0x64 - -#define PS2_KEYBOARD_COMMAND_WRITE 0x60 // 向键盘发送配置命令 -#define PS2_KEYBOARD_COMMAND_READ 0x20 // 读取键盘的配置值 -#define PS2_KEYBOARD_PARAM_INIT 0x47 // 初始化键盘控制器的配置值 - -// ========= 检测键盘控制器输入/输出缓冲区是否已满 -#define PS2_KEYBOARD_FLAG_OUTBUF_FULL 0x01 // 键盘的输出缓冲区已满标志位 -#define PS2_KEYBOARD_FLAG_INBUF_FULL 0x02 // 键盘的输入缓冲区已满标志位 - -// 等待向键盘控制器写入信息完成 -// todo: bugfix:在不包含ps2键盘控制器的机器上,这里会卡死 -#define wait_ps2_keyboard_write() \ - while (io_in8(PORT_PS2_KEYBOARD_STATUS) & PS2_KEYBOARD_FLAG_INBUF_FULL) -// #define wait_ps2_keyboard_write() (1) -// 等待从键盘控制器读取信息完成 -#define wait_ps2_keyboard_read() \ - while (io_in8(PORT_PS2_KEYBOARD_STATUS) & PS2_KEYBOARD_FLAG_OUTBUF_FULL) -// #define wait_ps2_keyboard_read() (1) - -extern struct vfs_file_operations_t ps2_keyboard_fops; - -/** - * @brief 键盘驱动卸载函数 - * - */ -void ps2_keyboard_exit(); diff --git a/kernel/src/driver/keyboard/ps2_keyboard.rs b/kernel/src/driver/keyboard/ps2_keyboard.rs index 1a011d55..3ccda94f 100644 --- a/kernel/src/driver/keyboard/ps2_keyboard.rs +++ b/kernel/src/driver/keyboard/ps2_keyboard.rs @@ -1,9 +1,24 @@ -use core::{ffi::c_void, sync::atomic::AtomicI32}; +use core::hint::spin_loop; -use alloc::sync::{Arc, Weak}; +use alloc::{ + string::ToString, + sync::{Arc, Weak}, +}; + +use unified_init::macros::unified_init; use crate::{ - driver::base::device::device_number::{DeviceNumber, Major}, + arch::{io::PortIOArch, CurrentPortIOArch}, + driver::{ + base::device::device_number::{DeviceNumber, Major}, + input::ps2_dev::Ps2StatusRegister, + }, + exception::{ + irqdata::IrqHandlerData, + irqdesc::{IrqHandleFlags, IrqHandler, IrqReturn}, + manage::irq_manager, + IrqNumber, + }, filesystem::{ devfs::{devfs_register, DevFS, DeviceINode}, vfs::{ @@ -11,13 +26,30 @@ use crate::{ FileSystem, FileType, IndexNode, Metadata, }, }, - include::bindings::bindings::vfs_file_operations_t, + init::initcall::INITCALL_DEVICE, libs::{keyboard_parser::TypeOneFSM, rwlock::RwLock, spinlock::SpinLock}, time::TimeSpec, }; use system_error::SystemError; + +/// PS2键盘的中断向量号 +const PS2_KEYBOARD_INTR_VECTOR: IrqNumber = IrqNumber::new(0x21); + +const PORT_PS2_KEYBOARD_DATA: u8 = 0x60; +const PORT_PS2_KEYBOARD_STATUS: u8 = 0x64; +const PORT_PS2_KEYBOARD_CONTROL: u8 = 0x64; + +/// 向键盘发送配置命令 +const PS2_KEYBOARD_COMMAND_WRITE: u8 = 0x60; + +/// 读取键盘的配置值 +#[allow(dead_code)] +const PS2_KEYBOARD_COMMAND_READ: u8 = 0x20; +/// 初始化键盘控制器的配置值 +const PS2_KEYBOARD_PARAM_INIT: u8 = 0x47; + #[derive(Debug)] -pub struct LockedPS2KeyBoardInode(RwLock, AtomicI32); // self.1 用来记录有多少个文件打开了这个inode +pub struct LockedPS2KeyBoardInode(RwLock); lazy_static! { static ref PS2_KEYBOARD_FSM: SpinLock = SpinLock::new(TypeOneFSM::new()); @@ -33,17 +65,14 @@ pub struct PS2KeyBoardInode { fs: Weak, /// INode 元数据 metadata: Metadata, - /// 键盘操作函数 - f_ops: vfs_file_operations_t, } impl LockedPS2KeyBoardInode { - pub fn new(f_ops: &vfs_file_operations_t) -> Arc { + pub fn new() -> Arc { let inode = PS2KeyBoardInode { // uuid: Uuid::new_v5(), self_ref: Weak::default(), fs: Weak::default(), - f_ops: f_ops.clone(), // 从引用复制一遍获取所有权 metadata: Metadata { dev_id: 1, inode_id: generate_inode_id(), @@ -62,10 +91,7 @@ impl LockedPS2KeyBoardInode { }, }; - let result = Arc::new(LockedPS2KeyBoardInode( - RwLock::new(inode), - AtomicI32::new(0), - )); + let result = Arc::new(LockedPS2KeyBoardInode(RwLock::new(inode))); result.0.write().self_ref = Arc::downgrade(&result); return result; @@ -78,9 +104,8 @@ impl DeviceINode for LockedPS2KeyBoardInode { } } -#[no_mangle] // 不重命名 -pub extern "C" fn ps2_keyboard_register(f_ops: &vfs_file_operations_t) { - devfs_register("ps2_keyboard", LockedPS2KeyBoardInode::new(f_ops)) +fn ps2_keyboard_register() { + devfs_register("ps2_keyboard", LockedPS2KeyBoardInode::new()) .expect("Failed to register ps/2 keyboard"); } @@ -88,21 +113,11 @@ impl IndexNode for LockedPS2KeyBoardInode { fn read_at( &self, _offset: usize, - len: usize, - buf: &mut [u8], + _len: usize, + _buf: &mut [u8], _data: &mut FilePrivateData, ) -> Result { - let guard = self.0.read(); - let func = guard.f_ops.read.unwrap(); - let r = unsafe { - func( - 0 as *mut c_void, - &mut buf[0..len] as *mut [u8] as *mut i8, - len as i64, - 0 as *mut i64, - ) - }; - return Ok(r as usize); + return Err(SystemError::ENOSYS); } fn write_at( @@ -112,28 +127,14 @@ impl IndexNode for LockedPS2KeyBoardInode { _buf: &[u8], _data: &mut FilePrivateData, ) -> Result { - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); + return Err(SystemError::ENOSYS); } fn open(&self, _data: &mut FilePrivateData, _mode: &FileMode) -> Result<(), SystemError> { - let prev_ref_count = self.1.fetch_add(1, core::sync::atomic::Ordering::SeqCst); - if prev_ref_count == 0 { - // 第一次打开,需要初始化 - let guard = self.0.write(); - let func = guard.f_ops.open.unwrap(); - let _ = unsafe { func(0 as *mut c_void, 0 as *mut c_void) }; - } return Ok(()); } fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> { - let prev_ref_count = self.1.fetch_sub(1, core::sync::atomic::Ordering::SeqCst); - if prev_ref_count == 1 { - // 最后一次关闭,需要释放 - let guard = self.0.write(); - let func = guard.f_ops.close.unwrap(); - let _ = unsafe { func(0 as *mut c_void, 0 as *mut c_void) }; - } return Ok(()); } @@ -166,9 +167,85 @@ impl IndexNode for LockedPS2KeyBoardInode { } } -#[allow(dead_code)] -#[no_mangle] -/// for test -pub extern "C" fn ps2_keyboard_parse_keycode(input: u8) { - PS2_KEYBOARD_FSM.lock().parse(input); +#[derive(Debug)] +struct Ps2KeyboardIrqHandler; + +impl IrqHandler for Ps2KeyboardIrqHandler { + fn handle( + &self, + _irq: IrqNumber, + _static_data: Option<&dyn IrqHandlerData>, + _dev_id: Option>, + ) -> Result { + // 先检查状态寄存器,看看是否有数据 + let status = unsafe { CurrentPortIOArch::in8(PORT_PS2_KEYBOARD_STATUS.into()) }; + let status = Ps2StatusRegister::from(status); + if !status.outbuf_full() { + return Ok(IrqReturn::NotHandled); + } + + let input = unsafe { CurrentPortIOArch::in8(PORT_PS2_KEYBOARD_DATA.into()) }; + // wait_ps2_keyboard_read(); + PS2_KEYBOARD_FSM.lock().parse(input); + + return Ok(IrqReturn::Handled); + } +} + +impl Ps2KeyboardIrqHandler { + const INTR_HANDLE_FLAGS: IrqHandleFlags = + IrqHandleFlags::from_bits_truncate(IrqHandleFlags::IRQF_TRIGGER_RISING.bits()); +} + +/// 等待 PS/2 键盘的输入缓冲区为空 +fn wait_ps2_keyboard_write() { + let mut status: Ps2StatusRegister; + loop { + status = Ps2StatusRegister::from(unsafe { + CurrentPortIOArch::in8(PORT_PS2_KEYBOARD_STATUS.into()) + }); + if !status.inbuf_full() { + break; + } + + spin_loop(); + } +} +#[unified_init(INITCALL_DEVICE)] +fn ps2_keyboard_init() -> Result<(), SystemError> { + // ======== 初始化键盘控制器,写入配置值 ========= + wait_ps2_keyboard_write(); + unsafe { + CurrentPortIOArch::out8(PORT_PS2_KEYBOARD_CONTROL.into(), PS2_KEYBOARD_COMMAND_WRITE); + wait_ps2_keyboard_write(); + CurrentPortIOArch::out8(PORT_PS2_KEYBOARD_DATA.into(), PS2_KEYBOARD_PARAM_INIT); + wait_ps2_keyboard_write(); + } + + // 执行一百万次nop,等待键盘控制器把命令执行完毕 + for _ in 0..1000000 { + spin_loop(); + } + + irq_manager() + .request_irq( + PS2_KEYBOARD_INTR_VECTOR, + "ps2keyboard".to_string(), + &Ps2KeyboardIrqHandler, + Ps2KeyboardIrqHandler::INTR_HANDLE_FLAGS, + None, + ) + .expect("Failed to request irq for ps2 keyboard"); + + // 先读一下键盘的数据,防止由于在键盘初始化之前,由于按键被按下从而导致接收不到中断。 + let status = unsafe { CurrentPortIOArch::in8(PORT_PS2_KEYBOARD_STATUS.into()) }; + let status = Ps2StatusRegister::from(status); + if status.outbuf_full() { + unsafe { CurrentPortIOArch::in8(PORT_PS2_KEYBOARD_DATA.into()) }; + } + + // 将设备挂载到devfs + ps2_keyboard_register(); + + Ok(()) } diff --git a/kernel/src/driver/mouse/Makefile b/kernel/src/driver/mouse/Makefile deleted file mode 100644 index f8513471..00000000 --- a/kernel/src/driver/mouse/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -SRC = $(wildcard *.c) -OBJ = $(SRC:.c=.o) -CFLAGS += -I . - -.PHONY: all - -all: $(OBJ) - -%.o: %.c - $(CC) $(CFLAGS) -c $< -o $@ \ No newline at end of file diff --git a/kernel/src/driver/mouse/ps2_mouse.c b/kernel/src/driver/mouse/ps2_mouse.c deleted file mode 100644 index aac1c110..00000000 --- a/kernel/src/driver/mouse/ps2_mouse.c +++ /dev/null @@ -1,58 +0,0 @@ -#include "ps2_mouse.h" -#include -#include -#include -#include -#include - -extern void ps2_mouse_driver_interrupt(); - -/** - * @brief 鼠标中断处理函数(中断上半部) - * 将数据存入缓冲区 - * @param irq_num 中断向量号 - * @param param 参数 - * @param regs 寄存器信息 - */ -void ps2_mouse_handler(ul irq_num, ul param, struct pt_regs *regs) -{ - ps2_mouse_driver_interrupt(); -} - -struct apic_IO_APIC_RTE_entry ps2_mouse_entry; - -hardware_intr_controller ps2_mouse_intr_controller = - { - .enable = apic_ioapic_enable, - .disable = apic_ioapic_disable, - .install = apic_ioapic_install, - .uninstall = apic_ioapic_uninstall, - .ack = apic_ioapic_edge_ack, - -}; - -/** - * @brief 初始化鼠标驱动程序 - * - */ -void c_ps2_mouse_init() -{ - // ======== 初始化中断RTE entry ========== - - ps2_mouse_entry.vector = PS2_MOUSE_INTR_VECTOR; // 设置中断向量号 - ps2_mouse_entry.deliver_mode = IO_APIC_FIXED; // 投递模式:混合 - ps2_mouse_entry.dest_mode = DEST_PHYSICAL; // 物理模式投递中断 - ps2_mouse_entry.deliver_status = IDLE; - ps2_mouse_entry.trigger_mode = EDGE_TRIGGER; // 设置边沿触发 - ps2_mouse_entry.polarity = POLARITY_HIGH; // 高电平触发 - ps2_mouse_entry.remote_IRR = IRR_RESET; - ps2_mouse_entry.mask = MASKED; - ps2_mouse_entry.reserved = 0; - - ps2_mouse_entry.destination.physical.reserved1 = 0; - ps2_mouse_entry.destination.physical.reserved2 = 0; - ps2_mouse_entry.destination.physical.phy_dest = 0; // 设置投递到BSP处理器 - - // 注册中断处理程序 - irq_register(PS2_MOUSE_INTR_VECTOR, &ps2_mouse_entry, &ps2_mouse_handler, 0, &ps2_mouse_intr_controller, "ps/2 mouse"); -} \ No newline at end of file diff --git a/kernel/src/driver/mouse/ps2_mouse.h b/kernel/src/driver/mouse/ps2_mouse.h deleted file mode 100644 index 743c5430..00000000 --- a/kernel/src/driver/mouse/ps2_mouse.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include - -#define PS2_MOUSE_INTR_VECTOR 0x2c // 鼠标的中断向量号 - -#define KEYBOARD_COMMAND_SEND_TO_PS2_MOUSE 0xd4 // 键盘控制器向鼠标设备发送数据的命令 - -#define PS2_MOUSE_GET_ID 0xf2 // 获取鼠标的ID -#define PS2_MOUSE_SET_SAMPLING_RATE 0xf3 // 设置鼠标的采样率 -#define PS2_MOUSE_ENABLE 0xf4 // 允许鼠标设备发送数据包 -#define PS2_MOUSE_DISABLE 0xf5 // 禁止鼠标设备发送数据包 -#define PS2_MOUSE_SET_DEFAULT_SAMPLING_RATE 0xf6 // 设置使用默认采样率100hz,分辨率4px/mm -#define PS2_MOUSE_RESEND_LAST_PACKET 0xfe // 重新发送上一条数据包 -#define PS2_MOUSE_RESET 0xff // 重启鼠标 - -#define KEYBOARD_COMMAND_ENABLE_PS2_MOUSE_PORT 0xa8 // 通过键盘控制器开启鼠标端口的命令 - -#define ps2_mouse_buffer_size 360 - -#define PORT_KEYBOARD_DATA 0x60 -#define PORT_KEYBOARD_STATUS 0x64 -#define PORT_KEYBOARD_CONTROL 0x64 - -#define KEYBOARD_COMMAND_WRITE 0x60 // 向键盘发送配置命令 -#define KEYBOARD_COMMAND_READ 0x20 // 读取键盘的配置值 -#define KEYBOARD_PARAM_INIT 0x47 // 初始化键盘控制器的配置值 - -// ========= 检测键盘控制器输入/输出缓冲区是否已满 -#define KEYBOARD_FLAG_OUTBUF_FULL 0x01 // 键盘的输出缓冲区已满标志位 -#define KEYBOARD_FLAG_INBUF_FULL 0x02 // 键盘的输入缓冲区已满标志位 - - -/** - * @brief 初始化鼠标驱动程序 - * - */ -void c_ps2_mouse_init(); diff --git a/kernel/src/driver/net/e1000e/e1000e.rs b/kernel/src/driver/net/e1000e/e1000e.rs index 21e4ee4a..aebede80 100644 --- a/kernel/src/driver/net/e1000e/e1000e.rs +++ b/kernel/src/driver/net/e1000e/e1000e.rs @@ -1,6 +1,8 @@ // 参考手册: PCIe* GbE Controllers Open Source Software Developer’s Manual // Refernce: PCIe* GbE Controllers Open Source Software Developer’s Manual +use alloc::string::ToString; +use alloc::sync::Arc; use alloc::vec::Vec; use core::intrinsics::unlikely; use core::mem::size_of; @@ -9,15 +11,18 @@ use core::slice::{from_raw_parts, from_raw_parts_mut}; use core::sync::atomic::{compiler_fence, Ordering}; use super::e1000e_driver::e1000e_driver_init; +use crate::driver::base::device::DeviceId; use crate::driver::net::dma::{dma_alloc, dma_dealloc}; +use crate::driver::net::irq_handle::DefaultNetIrqHandler; use crate::driver::pci::pci::{ get_pci_device_structure_mut, PciDeviceStructure, PciDeviceStructureGeneralDevice, PciError, PCI_DEVICE_LINKEDLIST, }; use crate::driver::pci::pci_irq::{IrqCommonMsg, IrqSpecificMsg, PciInterrupt, PciIrqMsg, IRQ}; -use crate::include::bindings::bindings::pt_regs; +use crate::exception::IrqNumber; + use crate::libs::volatile::{ReadOnly, Volatile, WriteOnly}; -use crate::net::net_core::poll_ifaces_try_lock_onetime; + use crate::{kdebug, kinfo}; const PAGE_SIZE: usize = 4096; @@ -55,7 +60,7 @@ const E1000E_REG_SIZE: u8 = 4; const E1000E_DMA_PAGES: usize = 1; // 中断相关 -const E1000E_RECV_VECTOR: u16 = 57; +const E1000E_RECV_VECTOR: IrqNumber = IrqNumber::new(57); // napi队列中暂时存储的buffer个数 const E1000E_RECV_NAPI: usize = 1024; @@ -157,12 +162,6 @@ impl E1000EBuffer { } } -// 中断处理函数, 调用协议栈的poll函数,未来可能会用napi来替换这里 -// Interrupt handler -unsafe extern "C" fn e1000e_irq_handler(_irq_num: u64, _irq_paramer: u64, _regs: *mut pt_regs) { - poll_ifaces_try_lock_onetime().ok(); -} - #[allow(dead_code)] pub struct E1000EDevice { // 设备寄存器 @@ -201,7 +200,10 @@ impl E1000EDevice { // 从PCI标准设备进行驱动初始化 // init the device for PCI standard device struct #[allow(unused_assignments)] - pub fn new(device: &mut PciDeviceStructureGeneralDevice) -> Result { + pub fn new( + device: &mut PciDeviceStructureGeneralDevice, + device_id: Arc, + ) -> Result { // 从BAR0获取我们需要的寄存器 // Build registers sturcts from BAR0 device.bar_ioremap().unwrap()?; @@ -230,10 +232,9 @@ impl E1000EDevice { let msg = PciIrqMsg { irq_common_message: IrqCommonMsg::init_from( 0, - "E1000E_RECV_IRQ", - 0, - e1000e_irq_handler, - None, + "E1000E_RECV_IRQ".to_string(), + &DefaultNetIrqHandler, + device_id, ), irq_specific_message: IrqSpecificMsg::msi_default(), }; @@ -619,7 +620,12 @@ pub fn e1000e_probe() -> Result { "Detected e1000e PCI device with device id {:#x}", header.device_id ); - let e1000e = E1000EDevice::new(standard_device)?; + + // todo: 根据pci的path来生成device id + let e1000e = E1000EDevice::new( + standard_device, + DeviceId::new(None, Some(format!("e1000e_{}", header.device_id))).unwrap(), + )?; e1000e_driver_init(e1000e); } } diff --git a/kernel/src/driver/net/irq_handle.rs b/kernel/src/driver/net/irq_handle.rs new file mode 100644 index 00000000..6a1a3a32 --- /dev/null +++ b/kernel/src/driver/net/irq_handle.rs @@ -0,0 +1,27 @@ +use alloc::sync::Arc; +use system_error::SystemError; + +use crate::{ + exception::{ + irqdata::IrqHandlerData, + irqdesc::{IrqHandler, IrqReturn}, + IrqNumber, + }, + net::net_core::poll_ifaces_try_lock_onetime, +}; + +/// 默认的网卡中断处理函数 +#[derive(Debug)] +pub struct DefaultNetIrqHandler; + +impl IrqHandler for DefaultNetIrqHandler { + fn handle( + &self, + _irq: IrqNumber, + _static_data: Option<&dyn IrqHandlerData>, + _dynamic_data: Option>, + ) -> Result { + poll_ifaces_try_lock_onetime().ok(); + Ok(IrqReturn::Handled) + } +} diff --git a/kernel/src/driver/net/mod.rs b/kernel/src/driver/net/mod.rs index b5cb7379..e01fa789 100644 --- a/kernel/src/driver/net/mod.rs +++ b/kernel/src/driver/net/mod.rs @@ -10,6 +10,7 @@ use system_error::SystemError; mod dma; pub mod e1000e; +pub mod irq_handle; pub mod virtio_net; pub trait NetDriver: Driver { diff --git a/kernel/src/driver/net/virtio_net.rs b/kernel/src/driver/net/virtio_net.rs index c4a0ee41..8d0a2a84 100644 --- a/kernel/src/driver/net/virtio_net.rs +++ b/kernel/src/driver/net/virtio_net.rs @@ -15,14 +15,15 @@ use super::NetDriver; use crate::{ driver::{ base::{ - device::{bus::Bus, driver::Driver, Device, IdTable}, + device::{bus::Bus, driver::Driver, Device, DeviceId, IdTable}, kobject::{KObjType, KObject, KObjectState}, }, - virtio::virtio_impl::HalImpl, + virtio::{irq::virtio_irq_manager, virtio_impl::HalImpl, VirtIODevice}, }, + exception::{irqdesc::IrqReturn, IrqNumber}, kerror, kinfo, libs::spinlock::SpinLock, - net::{generate_iface_id, NET_DRIVERS}, + net::{generate_iface_id, net_core::poll_ifaces_try_lock_onetime, NET_DRIVERS}, time::Instant, }; use system_error::SystemError; @@ -40,7 +41,8 @@ impl Clone for VirtioNICDriver { } } -/// @brief 网卡驱动的包裹器,这是为了获取网卡驱动的可变引用而设计的。 +/// 网卡驱动的包裹器,这是为了获取网卡驱动的可变引用而设计的。 +/// /// 由于smoltcp的设计,导致需要在poll的时候获取网卡驱动的可变引用, /// 同时需要在token的consume里面获取可变引用。为了避免双重加锁,所以需要这个包裹器。 struct VirtioNICDriverWrapper(UnsafeCell>); @@ -76,6 +78,7 @@ pub struct VirtioInterface { iface_id: usize, iface: SpinLock, name: String, + dev_id: Arc, } impl Debug for VirtioInterface { @@ -90,7 +93,7 @@ impl Debug for VirtioInterface { } impl VirtioInterface { - pub fn new(mut driver: VirtioNICDriver) -> Arc { + pub fn new(mut driver: VirtioNICDriver, dev_id: Arc) -> Arc { let iface_id = generate_iface_id(); let mut iface_config = smoltcp::iface::Config::new(); @@ -109,12 +112,31 @@ impl VirtioInterface { iface_id, iface: SpinLock::new(iface), name: format!("eth{}", iface_id), + dev_id, }); return result; } } +impl VirtIODevice for VirtioInterface { + fn handle_irq(&self, _irq: IrqNumber) -> Result { + poll_ifaces_try_lock_onetime().ok(); + return Ok(IrqReturn::Handled); + } + + fn dev_id(&self) -> &Arc { + return &self.dev_id; + } +} + +impl Drop for VirtioInterface { + fn drop(&mut self) { + // 从全局的网卡接口信息表中删除这个网卡的接口信息 + NET_DRIVERS.write_irqsave().remove(&self.iface_id); + } +} + impl VirtioNICDriver { pub fn new(driver_net: VirtIONet) -> Self { let mut iface_config = smoltcp::iface::Config::new(); @@ -223,7 +245,7 @@ impl phy::RxToken for VirtioNetToken { } /// @brief virtio-net 驱动的初始化与测试 -pub fn virtio_net(transport: T) { +pub fn virtio_net(transport: T, dev_id: Arc) { let driver_net: VirtIONet = match VirtIONet::::new(transport, 4096) { Ok(net) => net, @@ -234,12 +256,16 @@ pub fn virtio_net(transport: T) { }; let mac = smoltcp::wire::EthernetAddress::from_bytes(&driver_net.mac_address()); let driver: VirtioNICDriver = VirtioNICDriver::new(driver_net); - let iface = VirtioInterface::new(driver); + let iface = VirtioInterface::new(driver, dev_id); let name = iface.name.clone(); // 将网卡的接口信息注册到全局的网卡接口信息表中 NET_DRIVERS .write_irqsave() .insert(iface.nic_id(), iface.clone()); + + virtio_irq_manager() + .register_device(iface.clone()) + .expect("Register virtio net failed"); kinfo!( "Virtio-net driver init successfully!\tNetDevID: [{}], MAC: [{}]", name, diff --git a/kernel/src/driver/pci/Makefile b/kernel/src/driver/pci/Makefile deleted file mode 100644 index a505ba89..00000000 --- a/kernel/src/driver/pci/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -SRC = $(wildcard *.c) -OBJ = $(SRC:.c=.o) -CFLAGS += -I . - -.PHONY: all - -all: $(OBJ) - -%.o: %.c - $(CC) $(CFLAGS) -c $< -o $@ - diff --git a/kernel/src/driver/pci/pci.rs b/kernel/src/driver/pci/pci.rs index 3b1f14e5..8c7a0ab8 100644 --- a/kernel/src/driver/pci/pci.rs +++ b/kernel/src/driver/pci/pci.rs @@ -3,6 +3,7 @@ use super::pci_irq::{IrqType, PciIrqError}; use crate::arch::{PciArch, TraitPciArch}; +use crate::exception::IrqNumber; use crate::include::bindings::bindings::PAGE_2M_SIZE; use crate::libs::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}; @@ -371,7 +372,7 @@ pub trait PciDeviceStructure: Send + Sync { /// @brief 返回结构体中的irq_type的可变引用 fn irq_type_mut(&mut self) -> Option<&mut IrqType>; /// @brief 返回结构体中的irq_vector的可变引用 - fn irq_vector_mut(&mut self) -> Option<&mut Vec>; + fn irq_vector_mut(&mut self) -> Option<&mut Vec>; } /// Pci_Device_Structure_Header PCI设备结构体共有的头部 @@ -404,7 +405,7 @@ pub struct PciDeviceStructureGeneralDevice { // 中断结构体,包括legacy,msi,msix三种情况 pub irq_type: IrqType, // 使用的中断号的vec集合 - pub irq_vector: Vec, + pub irq_vector: Vec, pub standard_device_bar: PciStandardDeviceBar, pub cardbus_cis_pointer: u32, // 指向卡信息结构,供在 CardBus 和 PCI 之间共享芯片的设备使用。 pub subsystem_vendor_id: u16, @@ -464,7 +465,7 @@ impl PciDeviceStructure for PciDeviceStructureGeneralDevice { Some(&mut self.irq_type) } #[inline(always)] - fn irq_vector_mut(&mut self) -> Option<&mut Vec> { + fn irq_vector_mut(&mut self) -> Option<&mut Vec> { Some(&mut self.irq_vector) } } @@ -476,7 +477,7 @@ pub struct PciDeviceStructurePciToPciBridge { // 中断结构体,包括legacy,msi,msix三种情况 pub irq_type: IrqType, // 使用的中断号的vec集合 - pub irq_vector: Vec, + pub irq_vector: Vec, pub bar0: u32, pub bar1: u32, pub primary_bus_number: u8, @@ -528,7 +529,7 @@ impl PciDeviceStructure for PciDeviceStructurePciToPciBridge { Some(&mut self.irq_type) } #[inline(always)] - fn irq_vector_mut(&mut self) -> Option<&mut Vec> { + fn irq_vector_mut(&mut self) -> Option<&mut Vec> { Some(&mut self.irq_vector) } } @@ -587,7 +588,7 @@ impl PciDeviceStructure for PciDeviceStructurePciToCardbusBridge { None } #[inline(always)] - fn irq_vector_mut(&mut self) -> Option<&mut Vec> { + fn irq_vector_mut(&mut self) -> Option<&mut Vec> { None } } diff --git a/kernel/src/driver/pci/pci_irq.c b/kernel/src/driver/pci/pci_irq.c deleted file mode 100644 index 5c5cbe53..00000000 --- a/kernel/src/driver/pci/pci_irq.c +++ /dev/null @@ -1,95 +0,0 @@ -#include "pci_irq.h" -#include "exception/irq.h" -#include -#include -#include "common/string.h" -#include "mm/slab.h" - -// 现在pci设备的中断由自己进行控制,这些不执行内容的函数是为了适配旧的中断处理机制 -void pci_irq_enable(ul irq_num) -{ -} -void pci_irq_disable(ul irq_num) -{ -} -ul pci_irq_install(ul num , void* data) -{ -} -void pci_irq_uninstall(ul irq_num) -{ -} -/// @brief 与本操作系统的中断机制进行交互,把中断处理函数等注册到中断结构体中(被rust调用) -/// @param irq_num 要进行注册的中断号 -/// @param pci_irq_handler 对应的中断处理函数 -/// @param parameter 中断处理函数传入参数 -/// @param irq_name 中断名字 -/// @param pci_irq_ack 对于中断的回复,为NULL时会使用默认回应 -uint16_t c_irq_install(ul irq_num, void (*pci_irq_handler)(ul irq_num, ul parameter, struct pt_regs *regs), ul parameter, const char *irq_name, void (*pci_irq_ack)(ul irq_num)) -{ - // 由于为I/O APIC分配的中断向量号是从32开始的,因此要减去32才是对应的interrupt_desc的元素 - irq_desc_t *p = NULL; - hardware_intr_controller *pci_interrupt_controller = NULL; - if (irq_num >= 32 && irq_num < 0x80) - p = &interrupt_desc[irq_num - 32]; - else if (irq_num >= 150 && irq_num < 200) - p = &local_apic_interrupt_desc[irq_num - 150]; - else - { - // kerror("irq install for pci irq: invalid irq num: %ld.", irq_num); - return EINVAL; - } - if (p->irq_name != NULL) - { - return EAGAIN; - } - pci_interrupt_controller = kzalloc(sizeof(hardware_intr_controller), 0); - if (pci_interrupt_controller) - { - pci_interrupt_controller->enable = pci_irq_enable; - pci_interrupt_controller->disable = pci_irq_disable; - pci_interrupt_controller->install = pci_irq_install; - pci_interrupt_controller->uninstall = pci_irq_uninstall; - pci_interrupt_controller->ack = pci_irq_ack; - p->controller = pci_interrupt_controller; - } - else - { - return EAGAIN; - } - size_t namelen = strlen(irq_name) + 1; - p->irq_name = (char *)kzalloc(namelen, 0); - memset(p->irq_name, 0, namelen); - strncpy(p->irq_name, irq_name, namelen); - p->parameter = parameter; - p->flags = 0; - p->handler = pci_irq_handler; - return 0; -}; - -/// @brief 与本操作系统的中断机制进行交互,把中断处理函数等从中断结构体中移除,需要释放空间的进行空间的释放 -/// @param irq_num 要进行注销的中断号 -void c_irq_uninstall(ul irq_num) -{ - // 由于为I/O APIC分配的中断向量号是从32开始的,因此要减去32才是对应的interrupt_desc的元素 - irq_desc_t *p = NULL; - if (irq_num >= 32 && irq_num < 0x80) - p = &interrupt_desc[irq_num - 32]; - else if (irq_num >= 150 && irq_num < 200) - p = &local_apic_interrupt_desc[irq_num - 150]; - else - { - kerror("irq install for pci irq: invalid irq num: %ld.", irq_num); - } - if (p->irq_name != NULL) - { - kfree(p->irq_name); - p->irq_name = NULL; - } - if (p->controller != NULL) - { - kfree(p->controller); - p->controller = NULL; - } - p->parameter = 0; - p->handler = NULL; -} \ No newline at end of file diff --git a/kernel/src/driver/pci/pci_irq.h b/kernel/src/driver/pci/pci_irq.h deleted file mode 100644 index 4de4bd95..00000000 --- a/kernel/src/driver/pci/pci_irq.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once -#include -#include -uint16_t c_irq_install(ul irq_num,void (*pci_irq_handler)(ul irq_num, ul parameter, struct pt_regs *regs),ul parameter,const char *irq_name,void (*pci_irq_ack)(ul irq_num)); -void c_irq_uninstall(ul irq_num); \ No newline at end of file diff --git a/kernel/src/driver/pci/pci_irq.rs b/kernel/src/driver/pci/pci_irq.rs index d0a2ed7f..4907a579 100644 --- a/kernel/src/driver/pci/pci_irq.rs +++ b/kernel/src/driver/pci/pci_irq.rs @@ -3,16 +3,19 @@ use core::mem::size_of; use core::ptr::NonNull; -use alloc::ffi::CString; +use alloc::string::String; +use alloc::sync::Arc; use alloc::vec::Vec; +use system_error::SystemError; use super::pci::{PciDeviceStructure, PciDeviceStructureGeneralDevice, PciError}; use crate::arch::msi::{arch_msi_message_address, arch_msi_message_data}; use crate::arch::{PciArch, TraitPciArch}; -use crate::include::bindings::bindings::{ - c_irq_install, c_irq_uninstall, pt_regs, ul, EAGAIN, EINVAL, -}; +use crate::driver::base::device::DeviceId; +use crate::exception::irqdesc::{IrqHandleFlags, IrqHandler}; +use crate::exception::manage::irq_manager; +use crate::exception::IrqNumber; use crate::libs::volatile::{volread, volwrite, Volatile}; /// MSIX表的一项 @@ -37,8 +40,8 @@ pub enum PciIrqError { PciDeviceNotSupportIrq, IrqTypeUnmatch, InvalidIrqIndex(u16), - InvalidIrqNum(u16), - IrqNumOccupied(u16), + InvalidIrqNum(IrqNumber), + IrqNumOccupied(IrqNumber), DeviceIrqOverflow, MxiIrqNumWrong, PciBarNotInited, @@ -78,29 +81,35 @@ pub struct PciIrqMsg { // PCI设备install中断时需要传递的共同参数 #[derive(Clone, Debug)] pub struct IrqCommonMsg { - irq_index: u16, //要install的中断号在PCI设备中的irq_vector的index - irq_name: CString, //中断名字 - irq_parameter: u16, //中断额外参数,可传入中断处理函数 - irq_hander: unsafe extern "C" fn(irq_num: ul, parameter: ul, regs: *mut pt_regs), // 中断处理函数 - irq_ack: Option, // 中断的ack,可为None,若为None则中断处理中会正常通知中断结束,不为None则调用传入的函数进行回复 + irq_index: u16, //要install的中断号在PCI设备中的irq_vector的index + irq_name: String, //中断名字 + irq_hander: &'static dyn IrqHandler, // 中断处理函数 + /// 全局设备标志符 + dev_id: Arc, } impl IrqCommonMsg { pub fn init_from( irq_index: u16, - irq_name: &str, - irq_parameter: u16, - irq_hander: unsafe extern "C" fn(irq_num: ul, parameter: ul, regs: *mut pt_regs), - irq_ack: Option, + irq_name: String, + irq_hander: &'static dyn IrqHandler, + dev_id: Arc, ) -> Self { IrqCommonMsg { irq_index, - irq_name: CString::new(irq_name).expect("CString::new failed"), - irq_parameter, + irq_name, irq_hander, - irq_ack, + dev_id, } } + + pub fn set_handler(&mut self, irq_hander: &'static dyn IrqHandler) { + self.irq_hander = irq_hander; + } + + pub fn dev_id(&self) -> &Arc { + &self.dev_id + } } // PCI设备install中断时需要传递的特有参数,Msi代表MSI与MSIX @@ -347,28 +356,43 @@ pub trait PciInterrupt: PciDeviceStructure { } let irq_num = self.irq_vector_mut().unwrap()[msg.irq_common_message.irq_index as usize]; + + let irq_num = IrqNumber::new(irq_num.into()); let common_msg = &msg.irq_common_message; - let result = unsafe { - c_irq_install( - irq_num as u64, - Some(common_msg.irq_hander), - common_msg.irq_parameter as u64, - common_msg.irq_name.as_ptr(), - common_msg.irq_ack, - ) - }; - match result as u32 { - EINVAL => { + + let result = irq_manager().request_irq( + irq_num, + common_msg.irq_name.clone(), + common_msg.irq_hander, + IrqHandleFlags::empty(), + Some(common_msg.dev_id.clone()), + ); + + match result { + Ok(_) => {} + Err(SystemError::EINVAL) => { return Err(PciError::PciIrqError(PciIrqError::InvalidIrqNum(irq_num))); } - EAGAIN => { + + Err(SystemError::EAGAIN_OR_EWOULDBLOCK) => { + return Err(PciError::PciIrqError(PciIrqError::IrqNumOccupied( + irq_num, + ))); + } + + Err(_) => { + kerror!( + "Failed to request pci irq {} for device {}", + irq_num.data(), + &common_msg.irq_name + ); return Err(PciError::PciIrqError(PciIrqError::IrqNumOccupied( irq_num, ))); } - _ => {} } - //MSI中断只需配置一次PCI寄存器 + + // MSI中断只需配置一次PCI寄存器 if common_msg.irq_index == 0 { let msg_address = arch_msi_message_address(0); let trigger = match msg.irq_specific_message { @@ -377,8 +401,8 @@ pub trait PciInterrupt: PciDeviceStructure { } IrqSpecificMsg::Msi { trigger_mode, .. } => trigger_mode, }; - let msg_data = arch_msi_message_data(irq_num, 0, trigger); - //写入Message Data和Message Address + let msg_data = arch_msi_message_data(irq_num.data() as u16, 0, trigger); + // 写入Message Data和Message Address if address_64 { PciArch::write_config( &self.common_header().bus_device_function, @@ -496,26 +520,39 @@ pub trait PciInterrupt: PciDeviceStructure { } let irq_num = self.irq_vector_mut().unwrap()[msg.irq_common_message.irq_index as usize]; + let common_msg = &msg.irq_common_message; - let result = unsafe { - c_irq_install( - irq_num as u64, - Some(common_msg.irq_hander), - common_msg.irq_parameter as u64, - common_msg.irq_name.as_ptr(), - common_msg.irq_ack, - ) - }; - match result as u32 { - EINVAL => { + + let result = irq_manager().request_irq( + irq_num, + common_msg.irq_name.clone(), + common_msg.irq_hander, + IrqHandleFlags::empty(), + Some(common_msg.dev_id.clone()), + ); + + match result { + Ok(_) => {} + Err(SystemError::EINVAL) => { return Err(PciError::PciIrqError(PciIrqError::InvalidIrqNum(irq_num))); } - EAGAIN => { + + Err(SystemError::EAGAIN_OR_EWOULDBLOCK) => { + return Err(PciError::PciIrqError(PciIrqError::IrqNumOccupied( + irq_num, + ))); + } + + Err(_) => { + kerror!( + "Failed to request pci irq {} for device {}", + irq_num.data(), + &common_msg.irq_name + ); return Err(PciError::PciIrqError(PciIrqError::IrqNumOccupied( irq_num, ))); } - _ => {} } let msg_address = arch_msi_message_address(0); @@ -525,7 +562,7 @@ pub trait PciInterrupt: PciDeviceStructure { } IrqSpecificMsg::Msi { trigger_mode, .. } => trigger_mode, }; - let msg_data = arch_msi_message_data(irq_num, 0, trigger); + let msg_data = arch_msi_message_data(irq_num.data() as u16, 0, trigger); //写入Message Data和Message Address let pcistandardbar = self .bar() @@ -589,9 +626,8 @@ pub trait PciInterrupt: PciDeviceStructure { .. } => { for vector in self.irq_vector_mut().unwrap() { - unsafe { - c_irq_uninstall(vector.clone() as u64); - } + let irq = IrqNumber::new((*vector).into()); + irq_manager().free_irq(irq, None); } PciArch::write_config(&self.common_header().bus_device_function, cap_offset, 0); PciArch::write_config( @@ -636,9 +672,8 @@ pub trait PciInterrupt: PciDeviceStructure { .. } => { for vector in self.irq_vector_mut().unwrap() { - unsafe { - c_irq_uninstall(vector.clone() as u64); - } + let irq = IrqNumber::new((*vector).into()); + irq_manager().free_irq(irq, None); } PciArch::write_config(&self.common_header().bus_device_function, cap_offset, 0); let pcistandardbar = self diff --git a/kernel/src/driver/virtio/irq.rs b/kernel/src/driver/virtio/irq.rs new file mode 100644 index 00000000..f3717888 --- /dev/null +++ b/kernel/src/driver/virtio/irq.rs @@ -0,0 +1,85 @@ +use alloc::sync::Arc; +use hashbrown::HashMap; +use system_error::SystemError; +use unified_init::macros::unified_init; + +use crate::{driver::base::device::DeviceId, init::initcall::INITCALL_CORE, libs::rwlock::RwLock}; + +use super::VirtIODevice; + +static mut VIRTIO_IRQ_MANAGER: Option = None; + +#[inline(always)] +pub fn virtio_irq_manager() -> &'static VirtIOIrqManager { + unsafe { VIRTIO_IRQ_MANAGER.as_ref().unwrap() } +} + +pub struct VirtIOIrqManager { + map: RwLock, Arc>>, +} + +impl VirtIOIrqManager { + fn new() -> Self { + VirtIOIrqManager { + map: RwLock::new(HashMap::new()), + } + } + + /// 注册一个新的设备到virtio中断请求(IRQ)映射中。 + /// + /// # 参数 + /// + /// - `device` - 实现了 `VirtIODevice` trait 的设备对象,被封装在 `Arc` 智能指针中。 + /// + /// # 返回值 + /// + /// - 如果设备成功注册,返回 `Ok(())`。 + /// - 如果设备ID已经存在于映射中,返回 `Err(SystemError::EEXIST)`。 + pub fn register_device(&self, device: Arc) -> Result<(), SystemError> { + let mut map = self.map.write_irqsave(); + + if map.contains_key(device.dev_id()) { + return Err(SystemError::EEXIST); + } + + map.insert(device.dev_id().clone(), device); + + return Ok(()); + } + + /// 取消注册设备 + /// + /// 这个函数会从内部映射中移除指定的设备。设备是通过设备ID来识别的。 + /// + /// # 参数 + /// + /// - `device` - 需要被取消注册的设备,它是一个实现了 `VirtIODevice` trait 的智能指针。 + #[allow(dead_code)] + pub fn unregister_device(&self, dev_id: &Arc) { + let mut map = self.map.write_irqsave(); + map.remove(dev_id); + } + + /// 查找并返回指定设备ID的设备。 + /// + /// # 参数 + /// - `dev_id` - 我们要查找的设备的设备ID。 + /// + /// # 返回 + /// - 如果找到了设备,返回一个包含设备的`Option>`。 + /// - 如果没有找到设备,返回`None`。 + + pub fn lookup_device(&self, dev_id: &Arc) -> Option> { + let map = self.map.read_irqsave(); + map.get(dev_id).map(|x| x.clone()) + } +} + +#[unified_init(INITCALL_CORE)] +fn init_virtio_irq_manager() -> Result<(), SystemError> { + let manager = VirtIOIrqManager::new(); + unsafe { + VIRTIO_IRQ_MANAGER = Some(manager); + } + return Ok(()); +} diff --git a/kernel/src/driver/virtio/mod.rs b/kernel/src/driver/virtio/mod.rs index f7b75594..6da95197 100644 --- a/kernel/src/driver/virtio/mod.rs +++ b/kernel/src/driver/virtio/mod.rs @@ -1,3 +1,19 @@ +use core::any::Any; + +use alloc::sync::Arc; +use system_error::SystemError; + +use crate::exception::{irqdesc::IrqReturn, IrqNumber}; + +use super::base::device::DeviceId; + +pub(super) mod irq; pub mod transport_pci; pub mod virtio; pub mod virtio_impl; + +pub trait VirtIODevice: Send + Sync + Any { + fn handle_irq(&self, _irq: IrqNumber) -> Result; + + fn dev_id(&self) -> &Arc; +} diff --git a/kernel/src/driver/virtio/transport_pci.rs b/kernel/src/driver/virtio/transport_pci.rs index 2e793c58..0453ad07 100644 --- a/kernel/src/driver/virtio/transport_pci.rs +++ b/kernel/src/driver/virtio/transport_pci.rs @@ -1,22 +1,31 @@ //! PCI transport for VirtIO. use crate::arch::{PciArch, TraitPciArch}; +use crate::driver::base::device::DeviceId; use crate::driver::pci::pci::{ BusDeviceFunction, PciDeviceStructure, PciDeviceStructureGeneralDevice, PciError, PciStandardDeviceBar, PCI_CAP_ID_VNDR, }; use crate::driver::pci::pci_irq::{IrqCommonMsg, IrqSpecificMsg, PciInterrupt, PciIrqMsg, IRQ}; -use crate::include::bindings::bindings::pt_regs; +use crate::driver::virtio::irq::virtio_irq_manager; +use crate::exception::irqdata::IrqHandlerData; +use crate::exception::irqdesc::{IrqHandler, IrqReturn}; + +use crate::exception::IrqNumber; + use crate::libs::volatile::{ volread, volwrite, ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly, }; use crate::mm::VirtAddr; -use crate::net::net_core::poll_ifaces_try_lock_onetime; + +use alloc::string::ToString; +use alloc::sync::Arc; use core::{ fmt::{self, Display, Formatter}, mem::{align_of, size_of}, ptr::{self, addr_of_mut, NonNull}, }; +use system_error::SystemError; use virtio_drivers::{ transport::{DeviceStatus, DeviceType, Transport}, Error, Hal, PhysAddr, @@ -57,7 +66,7 @@ const VIRTIO_PCI_CAP_ISR_CFG: u8 = 3; const VIRTIO_PCI_CAP_DEVICE_CFG: u8 = 4; /// Virtio设备接收中断的设备号 -const VIRTIO_RECV_VECTOR: u16 = 56; +const VIRTIO_RECV_VECTOR: IrqNumber = IrqNumber::new(56); /// Virtio设备接收中断的设备号的表项号 const VIRTIO_RECV_VECTOR_INDEX: u16 = 0; // 接收的queue号 @@ -82,6 +91,7 @@ fn device_type(pci_device_id: u16) -> DeviceType { /// PCI transport for VirtIO. /// /// Ref: 4.1 Virtio Over PCI Bus +#[allow(dead_code)] #[derive(Debug, Clone)] pub struct PciTransport { device_type: DeviceType, @@ -96,21 +106,24 @@ pub struct PciTransport { isr_status: NonNull>, /// The VirtIO device-specific configuration within some BAR. config_space: Option>, -} - -unsafe extern "C" fn virtio_irq_hander(_irq_num: u64, _irq_paramer: u64, _regs: *mut pt_regs) { - // kdebug!("12345"); - poll_ifaces_try_lock_onetime().ok(); + irq: IrqNumber, + dev_id: Arc, } impl PciTransport { /// Construct a new PCI VirtIO device driver for the given device function on the given PCI /// root controller. /// + /// ## 参数 /// + /// - `device` - The PCI device structure for the VirtIO device. + /// - `irq_handler` - An optional handler for the device's interrupt. If `None`, a default + /// handler `DefaultVirtioIrqHandler` will be used. pub fn new( device: &mut PciDeviceStructureGeneralDevice, + dev_id: Arc, ) -> Result { + let irq = VIRTIO_RECV_VECTOR; let header = &device.common_header; let bus_device_function = header.bus_device_function; if header.vendor_id != VIRTIO_VENDOR_ID { @@ -128,7 +141,7 @@ impl PciTransport { let standard_device = device.as_standard_device_mut().unwrap(); // 目前缺少对PCI设备中断号的统一管理,所以这里需要指定一个中断号。不能与其他中断重复 let irq_vector = standard_device.irq_vector_mut().unwrap(); - irq_vector.push(VIRTIO_RECV_VECTOR); + irq_vector.push(irq); standard_device .irq_init(IRQ::PCI_IRQ_MSIX) .expect("IRQ init failed"); @@ -136,10 +149,9 @@ impl PciTransport { let msg = PciIrqMsg { irq_common_message: IrqCommonMsg::init_from( 0, - "Virtio_Recv_IRQ", - 0, - virtio_irq_hander, - None, + "Virtio_IRQ".to_string(), + &DefaultVirtioIrqHandler, + dev_id.clone(), ), irq_specific_message: IrqSpecificMsg::msi_default(), }; @@ -222,6 +234,8 @@ impl PciTransport { notify_off_multiplier, isr_status, config_space, + irq, + dev_id, }) } } @@ -374,7 +388,9 @@ impl Transport for PciTransport { impl Drop for PciTransport { fn drop(&mut self) { // Reset the device when the transport is dropped. - self.set_status(DeviceStatus::empty()) + self.set_status(DeviceStatus::empty()); + + // todo: 调用pci的中断释放函数,并且在virtio_irq_manager里面删除对应的设备的中断 } } @@ -544,3 +560,36 @@ fn get_bar_region_slice( fn nonnull_slice_from_raw_parts(data: NonNull, len: usize) -> NonNull<[T]> { NonNull::new(ptr::slice_from_raw_parts_mut(data.as_ptr(), len)).unwrap() } + +/// `DefaultVirtioIrqHandler` 是一个默认的virtio设备中断处理程序。 +/// +/// 当虚拟设备产生中断时,该处理程序会被调用。 +/// +/// 它首先检查设备ID是否存在,然后尝试查找与设备ID关联的设备。 +/// 如果找到设备,它会调用设备的 `handle_irq` 方法来处理中断。 +/// 如果没有找到设备,它会记录一条警告并返回 `IrqReturn::NotHandled`,表示中断未被处理。 +#[derive(Debug)] +struct DefaultVirtioIrqHandler; + +impl IrqHandler for DefaultVirtioIrqHandler { + fn handle( + &self, + irq: IrqNumber, + _static_data: Option<&dyn IrqHandlerData>, + dev_id: Option>, + ) -> Result { + let dev_id = dev_id.ok_or(SystemError::EINVAL)?; + let dev_id = dev_id + .arc_any() + .downcast::() + .map_err(|_| SystemError::EINVAL)?; + + if let Some(dev) = virtio_irq_manager().lookup_device(&dev_id) { + return dev.handle_irq(irq); + } else { + // 未绑定具体设备,因此无法处理中断 + + return Ok(IrqReturn::NotHandled); + } + } +} diff --git a/kernel/src/driver/virtio/virtio.rs b/kernel/src/driver/virtio/virtio.rs index 86663d45..0f6b179d 100644 --- a/kernel/src/driver/virtio/virtio.rs +++ b/kernel/src/driver/virtio/virtio.rs @@ -1,5 +1,6 @@ use super::transport_pci::PciTransport; use super::virtio_impl::HalImpl; +use crate::driver::base::device::DeviceId; use crate::driver::net::virtio_net::virtio_net; use crate::driver::pci::pci::{ get_pci_device_structure_mut, PciDeviceStructure, PciDeviceStructureGeneralDevice, @@ -7,6 +8,7 @@ use crate::driver::pci::pci::{ }; use crate::libs::rwlock::RwLockWriteGuard; use crate::{kdebug, kerror, kwarn}; +use alloc::sync::Arc; use alloc::{boxed::Box, collections::LinkedList}; use virtio_drivers::transport::{DeviceType, Transport}; const NETWORK_CLASS: u8 = 0x2; @@ -23,14 +25,16 @@ pub fn virtio_probe() { let mut list = PCI_DEVICE_LINKEDLIST.write(); if let Ok(virtio_list) = virtio_device_search(&mut list) { for virtio_device in virtio_list { - match PciTransport::new::(virtio_device) { + let dev_id = virtio_device.common_header.device_id; + let dev_id = DeviceId::new(None, Some(format!("virtio_{}", dev_id))).unwrap(); + match PciTransport::new::(virtio_device, dev_id.clone()) { Ok(mut transport) => { kdebug!( "Detected virtio PCI device with device type {:?}, features {:#018x}", transport.device_type(), transport.read_device_features(), ); - virtio_device_init(transport); + virtio_device_init(transport, dev_id); } Err(err) => { kerror!("Pci transport create failed because of error: {}", err); @@ -43,7 +47,7 @@ pub fn virtio_probe() { } ///@brief 为virtio设备寻找对应的驱动进行初始化 -fn virtio_device_init(transport: impl Transport + 'static) { +fn virtio_device_init(transport: impl Transport + 'static, dev_id: Arc) { match transport.device_type() { DeviceType::Block => { kwarn!("Not support virtio_block device for now"); @@ -54,7 +58,7 @@ fn virtio_device_init(transport: impl Transport + 'static) { DeviceType::Input => { kwarn!("Not support virtio_input device for now"); } - DeviceType::Network => virtio_net(transport), + DeviceType::Network => virtio_net(transport, dev_id), t => { kwarn!("Unrecognized virtio device: {:?}", t); } diff --git a/kernel/src/exception/Makefile b/kernel/src/exception/Makefile deleted file mode 100644 index a9fac409..00000000 --- a/kernel/src/exception/Makefile +++ /dev/null @@ -1,8 +0,0 @@ - -CFLAGS += -I . - - -all: irq.o - -irq.o: irq.c - $(CC) $(CFLAGS) -c irq.c -o irq.o \ No newline at end of file diff --git a/kernel/src/exception/dummychip.rs b/kernel/src/exception/dummychip.rs index 181149d9..bb9eff5d 100644 --- a/kernel/src/exception/dummychip.rs +++ b/kernel/src/exception/dummychip.rs @@ -41,10 +41,23 @@ impl IrqChip for NoIrqChip { fn name(&self) -> &'static str { "none" } + + fn can_mask_ack(&self) -> bool { + false + } + fn irq_enable(&self, _irq: &Arc) -> Result<(), SystemError> { Ok(()) } + fn can_set_affinity(&self) -> bool { + false + } + + fn can_set_flow_type(&self) -> bool { + false + } + fn irq_disable(&self, _irq: &Arc) {} fn irq_ack(&self, irq: &Arc) { @@ -78,17 +91,26 @@ impl IrqChip for DummyIrqChip { "dummy" } + fn can_mask_ack(&self) -> bool { + false + } + fn irq_enable(&self, _irq: &Arc) -> Result<(), SystemError> { Ok(()) } + fn can_set_flow_type(&self) -> bool { + false + } + + fn can_set_affinity(&self) -> bool { + false + } + fn irq_disable(&self, _irq: &Arc) {} fn irq_ack(&self, _irq: &Arc) {} - fn irq_mask(&self, _irq: &Arc) {} - fn irq_unmask(&self, _irq: &Arc) {} - fn irq_startup(&self, _irq: &Arc) -> Result<(), SystemError> { Ok(()) } diff --git a/kernel/src/exception/handle.rs b/kernel/src/exception/handle.rs index 59141072..cddd11e2 100644 --- a/kernel/src/exception/handle.rs +++ b/kernel/src/exception/handle.rs @@ -1,10 +1,22 @@ -use alloc::sync::Arc; +use core::{intrinsics::unlikely, ops::BitAnd}; -use crate::arch::CurrentIrqArch; +use alloc::sync::Arc; +use system_error::SystemError; + +use crate::{ + arch::{interrupt::TrapFrame, CurrentIrqArch}, + exception::irqdesc::InnerIrqDesc, + libs::spinlock::SpinLockGuard, + process::{ProcessFlags, ProcessManager}, +}; use super::{ - irqdesc::{IrqDesc, IrqFlowHandler}, - InterruptArch, + irqdata::{IrqData, IrqHandlerData, IrqStatus}, + irqdesc::{ + InnerIrqAction, IrqDesc, IrqDescState, IrqFlowHandler, IrqReturn, ThreadedHandlerFlags, + }, + manage::{irq_manager, IrqManager}, + InterruptArch, IrqNumber, }; /// 获取用于处理错误的中断的处理程序 @@ -13,15 +25,220 @@ pub fn bad_irq_handler() -> &'static dyn IrqFlowHandler { &HandleBadIrq } +/// 获取用于处理快速EOI的中断的处理程序 +#[inline(always)] +pub fn fast_eoi_irq_handler() -> &'static dyn IrqFlowHandler { + &FastEOIIrqHandler +} + +/// 获取用于处理边沿触发中断的处理程序 +#[inline(always)] +pub fn edge_irq_handler() -> &'static dyn IrqFlowHandler { + &EdgeIrqHandler +} + /// handle spurious and unhandled irqs #[derive(Debug)] struct HandleBadIrq; impl IrqFlowHandler for HandleBadIrq { /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/handle.c?fi=handle_bad_irq#33 - fn handle(&self, irq_desc: &Arc) { + fn handle(&self, irq_desc: &Arc, _trap_frame: &mut TrapFrame) { // todo: print_irq_desc // todo: 增加kstat计数 CurrentIrqArch::ack_bad_irq(irq_desc.irq()); } } + +#[derive(Debug)] +struct FastEOIIrqHandler; + +impl IrqFlowHandler for FastEOIIrqHandler { + fn handle(&self, _irq_desc: &Arc, _trap_frame: &mut TrapFrame) { + // https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/chip.c?r=&mo=17578&fi=689#689 + todo!("FastEOIIrqHandler"); + } +} + +#[derive(Debug)] +struct EdgeIrqHandler; + +impl IrqFlowHandler for EdgeIrqHandler { + // https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/chip.c?fi=handle_edge_irq#775 + fn handle(&self, irq_desc: &Arc, _trap_frame: &mut TrapFrame) { + let mut desc_inner_guard: SpinLockGuard<'_, InnerIrqDesc> = irq_desc.inner(); + if !irq_may_run(&desc_inner_guard) { + // kdebug!("!irq_may_run"); + desc_inner_guard + .internal_state_mut() + .insert(IrqDescState::IRQS_PENDING); + mask_ack_irq(desc_inner_guard.irq_data()); + return; + } + + if desc_inner_guard.common_data().disabled() { + // kdebug!("desc_inner_guard.common_data().disabled()"); + desc_inner_guard + .internal_state_mut() + .insert(IrqDescState::IRQS_PENDING); + mask_ack_irq(desc_inner_guard.irq_data()); + return; + } + + let irq_data = desc_inner_guard.irq_data().clone(); + + irq_data.chip_info_read_irqsave().chip().irq_ack(&irq_data); + + loop { + if unlikely(desc_inner_guard.actions().is_empty()) { + kdebug!("no action for irq {}", irq_data.irq().data()); + irq_manager().mask_irq(&irq_data); + return; + } + + // 当我们在处理一个中断时,如果另一个中断到来,我们本可以屏蔽它. + // 如果在此期间没有被禁用,请重新启用它。 + if desc_inner_guard + .internal_state() + .contains(IrqDescState::IRQS_PENDING) + { + let status = desc_inner_guard.common_data().status(); + if status.disabled() == false && status.masked() { + // kdebug!("re-enable irq"); + irq_manager().unmask_irq(&desc_inner_guard); + } + } + + // kdebug!("handle_irq_event"); + + desc_inner_guard + .internal_state_mut() + .remove(IrqDescState::IRQS_PENDING); + desc_inner_guard.common_data().set_inprogress(); + + drop(desc_inner_guard); + + let _r = do_handle_irq_event(irq_desc); + + desc_inner_guard = irq_desc.inner(); + desc_inner_guard.common_data().clear_inprogress(); + + if !(desc_inner_guard + .internal_state() + .contains(IrqDescState::IRQS_PENDING) + && desc_inner_guard.common_data().disabled() == false) + { + break; + } + } + } +} + +/// 判断中断是否可以运行 +fn irq_may_run(desc_inner_guard: &SpinLockGuard<'_, InnerIrqDesc>) -> bool { + let mask = IrqStatus::IRQD_IRQ_INPROGRESS | IrqStatus::IRQD_WAKEUP_ARMED; + let status = desc_inner_guard.common_data().status(); + + // 如果中断不在处理中并且没有被唤醒,则可以运行 + if status.bitand(mask).is_empty() { + return true; + } + + // todo: 检查其他处理器是否在轮询当前中断 + return false; +} + +fn mask_ack_irq(irq_data: &Arc) { + let chip = irq_data.chip_info_read_irqsave().chip(); + if chip.can_mask_ack() { + chip.irq_mask_ack(&irq_data); + irq_data.common_data().set_masked(); + } else { + irq_manager().mask_irq(irq_data); + chip.irq_ack(&irq_data); + } +} + +impl IrqManager { + pub(super) fn do_irq_wake_thread( + &self, + desc: &Arc, + action_inner: &mut SpinLockGuard<'_, InnerIrqAction>, + ) { + let thread = action_inner.thread(); + + if thread.is_none() { + return; + } + + let thread = thread.unwrap(); + if thread.flags().contains(ProcessFlags::EXITING) { + return; + } + + // 如果线程已经在运行,我们不需要唤醒它 + if action_inner + .thread_flags_mut() + .test_and_set_bit(ThreadedHandlerFlags::IRQTF_RUNTHREAD) + { + return; + } + + desc.inc_threads_active(); + + ProcessManager::wakeup(&thread).ok(); + } +} + +/// 处理中断事件 +/// +/// https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/handle.c?fi=handle_irq_event#139 +#[inline(never)] +fn do_handle_irq_event(desc: &Arc) -> Result<(), SystemError> { + let desc_inner_guard = desc.inner(); + let irq_data = desc_inner_guard.irq_data().clone(); + let actions = desc_inner_guard.actions().clone(); + drop(desc_inner_guard); + + let irq = irq_data.irq(); + let mut r = Ok(IrqReturn::NotHandled); + + for action in actions { + let mut action_inner: SpinLockGuard<'_, InnerIrqAction> = action.inner(); + // kdebug!("do_handle_irq_event: action: {:?}", action_inner.name()); + let dynamic_data = action_inner + .dev_id() + .clone() + .map(|d| d as Arc); + r = action_inner + .handler() + .unwrap() + .handle(irq, None, dynamic_data); + + if let Ok(IrqReturn::WakeThread) = r { + if unlikely(action_inner.thread_fn().is_none()) { + warn_no_thread(irq, &mut action_inner); + } else { + irq_manager().do_irq_wake_thread(desc, &mut action_inner); + } + }; + } + + return r.map(|_| ()); +} + +fn warn_no_thread(irq: IrqNumber, action_inner: &mut SpinLockGuard<'_, InnerIrqAction>) { + // warn on once + if action_inner + .thread_flags_mut() + .test_and_set_bit(ThreadedHandlerFlags::IRQTF_WARNED) + { + return; + } + + kwarn!( + "irq {}, device {} returned IRQ_WAKE_THREAD, but no threaded handler", + irq.data(), + action_inner.name() + ); +} diff --git a/kernel/src/exception/init.rs b/kernel/src/exception/init.rs index 742865f7..2735c80b 100644 --- a/kernel/src/exception/init.rs +++ b/kernel/src/exception/init.rs @@ -2,7 +2,10 @@ use system_error::SystemError; use crate::arch::CurrentIrqArch; -use super::{dummychip::dummy_chip_init, irqdesc::early_irq_init, InterruptArch}; +use super::{ + dummychip::dummy_chip_init, irqdesc::early_irq_init, irqdomain::irq_domain_manager_init, + InterruptArch, +}; /// 初始化中断 #[inline(never)] @@ -10,6 +13,7 @@ pub fn irq_init() -> Result<(), SystemError> { // todo: 通用初始化 dummy_chip_init(); + irq_domain_manager_init(); early_irq_init().expect("early_irq_init failed"); // 初始化架构相关的中断 diff --git a/kernel/src/exception/ipi.rs b/kernel/src/exception/ipi.rs index 60d415cc..4a2ec9c5 100644 --- a/kernel/src/exception/ipi.rs +++ b/kernel/src/exception/ipi.rs @@ -1,9 +1,25 @@ +use alloc::sync::Arc; +use system_error::SystemError; + +use crate::{ + arch::{sched::sched, MMArch}, + mm::MemoryManagementArch, + smp::cpu::ProcessorId, +}; + +use super::{ + irqdata::IrqHandlerData, + irqdesc::{IrqHandler, IrqReturn}, + HardwareIrqNumber, IrqNumber, +}; + #[allow(dead_code)] #[derive(Debug, Copy, Clone, Eq, PartialEq)] -#[repr(u8)] pub enum IpiKind { KickCpu, FlushTLB, + /// 指定中断向量号 + SpecVector(HardwareIrqNumber), } /// IPI投递目标 @@ -17,5 +33,38 @@ pub enum IpiTarget { /// 除了当前CPU以外的所有CPU Other, /// 指定的CPU - Specified(usize), + Specified(ProcessorId), +} + +/// 处理跨核心CPU唤醒的IPI +#[derive(Debug)] +pub struct KickCpuIpiHandler; + +impl IrqHandler for KickCpuIpiHandler { + fn handle( + &self, + _irq: IrqNumber, + _static_data: Option<&dyn IrqHandlerData>, + _dynamic_data: Option>, + ) -> Result { + sched(); + Ok(IrqReturn::Handled) + } +} + +/// 处理TLB刷新的IPI +#[derive(Debug)] +pub struct FlushTLBIpiHandler; + +impl IrqHandler for FlushTLBIpiHandler { + fn handle( + &self, + _irq: IrqNumber, + _static_data: Option<&dyn IrqHandlerData>, + _dynamic_data: Option>, + ) -> Result { + unsafe { MMArch::invalidate_all() }; + + Ok(IrqReturn::Handled) + } } diff --git a/kernel/src/exception/irq.c b/kernel/src/exception/irq.c deleted file mode 100644 index 54f70a27..00000000 --- a/kernel/src/exception/irq.c +++ /dev/null @@ -1,84 +0,0 @@ - -#include "irq.h" -#include - - -#include -#include -#include -#include -#include - -#pragma GCC push_options -#pragma GCC optimize("O0") - -/** - * @brief 中断注册函数 - * - * @param irq_num 中断向量号 - * @param arg 传递给中断安装接口的参数 - * @param handler 中断处理函数 - * @param paramater 中断处理函数的参数 - * @param controller 中断控制器结构 - * @param irq_name 中断名 - * @return int - */ -int irq_register(ul irq_num, void *arg, void (*handler)(ul irq_num, ul parameter, struct pt_regs *regs), ul paramater, - hardware_intr_controller *controller, char *irq_name) -{ - // 由于为I/O APIC分配的中断向量号是从32开始的,因此要减去32才是对应的interrupt_desc的元素 - irq_desc_t *p = NULL; - if (irq_num >= 32 && irq_num < 0x80) - p = &interrupt_desc[irq_num - 32]; - else if (irq_num >= 150 && irq_num < 200) - p = &local_apic_interrupt_desc[irq_num - 150]; - else - { - kerror("irq_register(): invalid irq num: %ld.", irq_num); - return -EINVAL; - } - p->controller = controller; - if (p->irq_name == NULL) - { - int namelen = sizeof(strlen(irq_name) + 1); - p->irq_name = (char *)kmalloc(namelen, 0); - memset(p->irq_name, 0, namelen); - strncpy(p->irq_name, irq_name, namelen); - } - - p->parameter = paramater; - p->flags = 0; - p->handler = handler; - io_mfence(); - p->controller->install(irq_num, arg); - io_mfence(); - p->controller->enable(irq_num); - io_mfence(); - - return 0; -} - -/** - * @brief 中断注销函数 - * - * @param irq_num 中断向量号 - * @return int - */ -int irq_unregister(ul irq_num) -{ - irq_desc_t *p = &interrupt_desc[irq_num - 32]; - p->controller->disable(irq_num); - p->controller->uninstall(irq_num); - - p->controller = NULL; - if (p->irq_name) - kfree(p->irq_name); - p->irq_name = NULL; - p->parameter = (ul)NULL; - p->flags = 0; - p->handler = NULL; - - return 0; -} - -#pragma GCC optimize("O0") diff --git a/kernel/src/exception/irq.h b/kernel/src/exception/irq.h deleted file mode 100644 index 04b9d5ea..00000000 --- a/kernel/src/exception/irq.h +++ /dev/null @@ -1,175 +0,0 @@ -/** - * @file irq.h - * @author longjin - * @brief 中断处理程序 - * @version 0.1 - * @date 2022-01-28 - * - * @copyright Copyright (c) 2022 - * - */ - -#pragma once -#include - -#include -#pragma GCC push_options -#pragma GCC optimize ("O0") - -#define IRQ_NUM 26 -#define SMP_IRQ_NUM 10 -#define LOCAL_APIC_IRQ_NUM 50 - -extern void (*interrupt_table[IRQ_NUM])(void); -extern void do_IRQ(struct pt_regs *regs, ul number); - - -extern void (*SMP_interrupt_table[SMP_IRQ_NUM])(void); - -extern void (*syscall_intr_table[1])(void); -extern void (*local_apic_interrupt_table[LOCAL_APIC_IRQ_NUM])(void); - -/* ========= 中断向量分配表 ========== - -0~255 IDT - -0 ~ 31 trap fault abort for system - 0 devide error - 1 debug - 2 NMI - 3 breakpoint - 4 overflow - 5 bound range - 6 undefined opcode - 7 device not available - 8 double fault - 9 coprocessor segment overrun - 10 invalid TSS - 11 segment not present - 12 stack segment fault - 13 general protection - 14 page fault - 15 - 16 x87 FPU error - 17 alignment check - 18 machine check - 19 SIMD exception - 20 virtualization exception -21 ~ 31 Do not use - -32 ~ 55 I/O APIC - 32 8259A - 33 keyboard - 34 HPET timer 0,8254 counter 0 - 35 serial port A - 36 serial port B - 37 parallel port - 38 floppy - 39 parallel port - 40 RTC,HPET timer 1 - 41 Generic - 42 Generic - 43 HPET timer 2 - 44 HPET timer 3 / mouse - 45 FERR# - 46 SATA primary - 47 SATA secondary - 48 PIRQA - 49 PIRQB - 50 PIRQC - 51 PIRQD - 52 PIRQE - 53 PIRQF - 54 PIRQG - 55 PIRQH - 56 VIRTIO_RECV - 57 E1000E_RECV - - -0x80 system call -0x81 system interrupt 系统中断 - -[150,200) Local APIC - 150 CMCI - 151 Timer - 152 Thermal Monitor - 153 Performance Counter - 154 LINT0 - 155 LINT1 - 156 Error - 157 xhci_controller_0 - 158 xhci_controller_1 - 159 xhci_controller_2 - 160 xhci_controller_3 - -200 ~ 255 MP IPI - - 200 kick cpu 功能(使得某个核心立即运行进程调度) - -*/ - -#define APIC_TIMER_IRQ_NUM 151 - -typedef struct hardware_intr_type -{ - // 使能中断操作接口 - void (*enable)(ul irq_num); - // 禁止中断操作接口 - void (*disable)(ul irq_num); - - // 安装中断操作接口 - ul (*install)(ul irq_num, void *arg); - // 卸载中断操作接口 - void (*uninstall)(ul irq_num); - // 应答中断操作接口 - void (*ack)(ul irq_num); -} hardware_intr_controller; - -// 中断描述结构体 -typedef struct -{ - hardware_intr_controller *controller; - // 中断名 - char *irq_name; - // 中断处理函数的参数 - ul parameter; - // 中断处理函数 - void (*handler)(ul irq_num, ul parameter, struct pt_regs *regs); - - // 自定义的标志位 - ul flags; -} irq_desc_t; - - -// 这几个表一定要放在这里,否则在HPET初始化后收到中断,会产生page fault -irq_desc_t interrupt_desc[IRQ_NUM] = {0}; -irq_desc_t local_apic_interrupt_desc[LOCAL_APIC_IRQ_NUM] = {0}; -irq_desc_t SMP_IPI_desc[SMP_IRQ_NUM] = {0}; - - -/** - * @brief 中断注册函数 - * - * @param irq_num 中断向量号 - * @param arg 传递给中断安装接口的参数 - * @param handler 中断处理函数 - * @param paramater 中断处理函数的参数 - * @param controller 中断控制器结构 - * @param irq_name 中断名 - * @return int - */ -int irq_register(ul irq_num, void *arg, void (*handler)(ul irq_num, ul parameter, struct pt_regs *regs), ul paramater, hardware_intr_controller *controller, char *irq_name); - -/** - * @brief 中断注销函数 - * - * @param irq_num 中断向量号 - * @return int - */ -int irq_unregister(ul irq_num); - -/** - * @brief 初始化中断模块 - */ -void irq_init(); -#pragma GCC pop_options \ No newline at end of file diff --git a/kernel/src/exception/irqchip.rs b/kernel/src/exception/irqchip.rs index 4cca4903..c7048bd6 100644 --- a/kernel/src/exception/irqchip.rs +++ b/kernel/src/exception/irqchip.rs @@ -6,11 +6,15 @@ use alloc::{ }; use system_error::SystemError; -use crate::{libs::spinlock::SpinLock, mm::VirtAddr}; +use crate::{ + libs::{cpumask::CpuMask, spinlock::SpinLock}, + mm::VirtAddr, +}; use super::{ irqdata::{IrqData, IrqLineStatus}, irqdomain::IrqDomain, + manage::IrqManager, msi::MsiMsg, }; @@ -41,18 +45,58 @@ pub trait IrqChip: Sync + Send + Any + Debug { fn irq_ack(&self, irq: &Arc); /// mask an interrupt source - fn irq_mask(&self, _irq: &Arc) {} + /// + /// 用于屏蔽中断 + /// + /// 如果返回ENOSYS,则表明irq_mask()不支持. + /// + /// 如果返回错误,那么中断的屏蔽状态将不会改变。 + fn irq_mask(&self, _irq: &Arc) -> Result<(), SystemError> { + Err(SystemError::ENOSYS) + } + + /// 指示当前芯片是否实现了`irq_mask_ack`函数 + fn can_mask_ack(&self) -> bool; + /// ack and mask an interrupt source fn irq_mask_ack(&self, _irq: &Arc) {} + /// unmask an interrupt source - fn irq_unmask(&self, _irq: &Arc) {} + /// + /// 用于取消屏蔽中断 + /// + /// 如果返回ENOSYS,则表明irq_unmask()不支持. + fn irq_unmask(&self, _irq: &Arc) -> Result<(), SystemError> { + Err(SystemError::ENOSYS) + } /// end of interrupt fn irq_eoi(&self, _irq: &Arc) {} - // todo: set affinity + /// 指示当前芯片是否可以设置中断亲和性。 + fn can_set_affinity(&self) -> bool; + + /// 在SMP机器上设置CPU亲和性。 + /// + /// 如果force参数为真,它告诉驱动程序无条件地应用亲和性设置。 + /// 不需要对提供的亲和性掩码进行完整性检查。这用于CPU热插拔,其中目标CPU尚未在cpu_online_mask中设置。 + fn irq_set_affinity( + &self, + _irq: &Arc, + _cpu: &CpuMask, + _force: bool, + ) -> Result { + Err(SystemError::ENOSYS) + } /// retrigger an IRQ to the CPU - fn retrigger(&self, _irq: &Arc) {} + fn retrigger(&self, _irq: &Arc) -> Result<(), SystemError> { + Err(SystemError::ENOSYS) + } + + /// 指示当前芯片是否可以设置中断流类型。 + /// + /// 如果返回true,则可以调用irq_set_type()。 + fn can_set_flow_type(&self) -> bool; /// set the flow type of an interrupt /// @@ -62,7 +106,7 @@ pub trait IrqChip: Sync + Send + Any + Debug { &self, _irq: &Arc, _flow_type: IrqLineStatus, - ) -> Result<(), SystemError> { + ) -> Result { Err(SystemError::ENOSYS) } @@ -108,6 +152,8 @@ pub trait IrqChip: Sync + Send + Any + Debug { fn irq_release_resources(&self, _irq: &Arc) {} /// optional to compose message content for MSI + /// + /// 组装MSI消息并返回到msg中 fn irq_compose_msi_msg(&self, _irq: &Arc, _msg: &mut MsiMsg) {} /// optional to write message content for MSI @@ -163,7 +209,10 @@ pub enum IrqChipState { LineLevel, } -pub trait IrqChipData: Sync + Send + Any + Debug {} +/// 中断芯片的数据(per-irq的) +pub trait IrqChipData: Sync + Send + Any + Debug { + fn as_any_ref(&self) -> &dyn Any; +} bitflags! { /// 定义 IrqGcFlags 位标志 @@ -240,10 +289,23 @@ pub struct IrqChipType { // todo https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#1024 } +#[allow(dead_code)] +#[derive(Debug)] +pub enum IrqChipSetMaskResult { + /// core updates mask ok. + SetMaskOk, + /// core updates mask ok. No change. + SetMaskOkNoChange, + /// core updates mask ok. Done.(same as SetMaskOk) + /// + /// 支持堆叠irq芯片的特殊代码, 表示跳过所有子irq芯片。 + SetMaskOkDone, +} + bitflags! { /// IrqChip specific flags pub struct IrqChipFlags: u32 { - /// 在调用chip.irq_set_type()之前屏蔽 + /// 在调用chip.irq_set_type()之前屏蔽中断 const IRQCHIP_SET_TYPE_MASKED = 1 << 0; /// 只有在irq被处理时才发出irq_eoi() const IRQCHIP_EOI_IF_HANDLED = 1 << 1; @@ -269,3 +331,40 @@ bitflags! { const IRQCHIP_IMMUTABLE = 1 << 11; } } + +impl IrqManager { + /// Acknowledge the parent interrupt + #[allow(dead_code)] + pub fn irq_chip_ack_parent(&self, irq_data: &Arc) { + let parent_data = irq_data.parent_data().map(|p| p.upgrade()).flatten(); + + if let Some(parent_data) = parent_data { + let parent_chip = parent_data.chip_info_read_irqsave().chip(); + parent_chip.irq_ack(&parent_data); + } + } + + /// 在硬件中重新触发中断 + /// + /// 遍历中断域的层次结构,并检查是否存在一个硬件重新触发函数。如果存在则调用它 + pub fn irq_chip_retrigger_hierarchy(&self, irq_data: &Arc) -> Result<(), SystemError> { + let mut data: Option> = Some(irq_data.clone()); + loop { + if let Some(d) = data { + if let Err(e) = d.chip_info_read_irqsave().chip().retrigger(&d) { + if e == SystemError::ENOSYS { + data = d.parent_data().map(|p| p.upgrade()).flatten(); + } else { + return Err(e); + } + } else { + return Ok(()); + } + } else { + break; + } + } + + return Ok(()); + } +} diff --git a/kernel/src/exception/irqdata.rs b/kernel/src/exception/irqdata.rs index e57a10c4..8ad8b8a5 100644 --- a/kernel/src/exception/irqdata.rs +++ b/kernel/src/exception/irqdata.rs @@ -1,8 +1,13 @@ use core::{any::Any, fmt::Debug}; use alloc::sync::{Arc, Weak}; +use intertrait::CastFromSync; -use crate::libs::spinlock::SpinLock; +use crate::libs::{ + cpumask::CpuMask, + rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}, + spinlock::{SpinLock, SpinLockGuard}, +}; use super::{ irqchip::{IrqChip, IrqChipData}, @@ -22,6 +27,8 @@ pub struct IrqData { /// 中断号, 用于表示软件逻辑视角的中断号,全局唯一 irq: IrqNumber, inner: SpinLock, + + chip_info: RwLock, } impl IrqData { @@ -36,25 +43,28 @@ impl IrqData { inner: SpinLock::new(InnerIrqData { hwirq, common_data, - chip, - chip_data: None, + domain: None, parent_data: None, }), + chip_info: RwLock::new(InnerIrqChipInfo { + chip: Some(chip), + chip_data: None, + }), }; } pub fn irqd_set(&self, status: IrqStatus) { // clone是为了释放inner锁 - let common_data = self.inner.lock().common_data.clone(); - common_data.irqd_set(status); + let common_data = self.inner.lock_irqsave().common_data.clone(); + common_data.insert_status(status); } #[allow(dead_code)] pub fn irqd_clear(&self, status: IrqStatus) { // clone是为了释放inner锁 - let common_data = self.inner.lock().common_data.clone(); - common_data.irqd_clear(status); + let common_data = self.inner.lock_irqsave().common_data.clone(); + common_data.clear_status(status); } pub fn irq(&self) -> IrqNumber { @@ -65,17 +75,13 @@ impl IrqData { self.inner.lock_irqsave().hwirq } - pub fn chip(&self) -> Arc { - self.inner.lock_irqsave().chip.clone() - } - /// 是否为电平触发 pub fn is_level_type(&self) -> bool { self.inner .lock_irqsave() .common_data .inner - .lock() + .lock_irqsave() .state .is_level_type() } @@ -85,29 +91,95 @@ impl IrqData { .lock_irqsave() .common_data .inner - .lock() + .lock_irqsave() .state .is_wakeup_set() } + + pub fn common_data(&self) -> Arc { + self.inner.lock_irqsave().common_data.clone() + } + + pub fn domain(&self) -> Option> { + self.inner.lock_irqsave().domain.clone() + } + + pub fn inner(&self) -> SpinLockGuard { + self.inner.lock_irqsave() + } + + pub fn chip_info_read(&self) -> RwLockReadGuard { + self.chip_info.read() + } + + pub fn chip_info_read_irqsave(&self) -> RwLockReadGuard { + self.chip_info.read_irqsave() + } + + pub fn chip_info_write_irqsave(&self) -> RwLockWriteGuard { + self.chip_info.write_irqsave() + } + + pub fn parent_data(&self) -> Option> { + self.inner.lock_irqsave().parent_data.clone() + } } #[allow(dead_code)] #[derive(Debug)] -struct InnerIrqData { +pub struct InnerIrqData { /// 硬件中断号, 用于表示在某个IrqDomain中的中断号 hwirq: HardwareIrqNumber, /// 涉及的所有irqchip之间共享的数据 common_data: Arc, - /// 绑定到的中断芯片 - chip: Arc, - /// 中断芯片的私有数据(与当前irq相关) - chip_data: Option>, + /// 中断域 domain: Option>, /// 中断的父中断(如果具有中断域继承的话) parent_data: Option>, } +impl InnerIrqData { + pub fn set_hwirq(&mut self, hwirq: HardwareIrqNumber) { + self.hwirq = hwirq; + } + + #[allow(dead_code)] + pub fn domain(&self) -> Option> { + self.domain.clone() + } + + pub fn set_domain(&mut self, domain: Option>) { + self.domain = domain; + } +} + +#[derive(Debug)] +pub struct InnerIrqChipInfo { + /// 绑定到的中断芯片 + chip: Option>, + /// 中断芯片的私有数据(与当前irq相关) + chip_data: Option>, +} + +impl InnerIrqChipInfo { + pub fn set_chip(&mut self, chip: Option>) { + self.chip = chip; + } + + pub fn set_chip_data(&mut self, chip_data: Option>) { + self.chip_data = chip_data; + } + + pub fn chip(&self) -> Arc { + self.chip.clone().unwrap() + } + + pub fn chip_data(&self) -> Option> { + self.chip_data.clone() + } +} + /// per irq data shared by all irqchips /// /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#147 @@ -122,19 +194,100 @@ impl IrqCommonData { state: IrqStatus::empty(), handler_data: None, msi_desc: None, + affinity: CpuMask::new(), }; return IrqCommonData { inner: SpinLock::new(inner), }; } - pub fn irqd_set(&self, status: IrqStatus) { - self.inner.lock_irqsave().irqd_set(status); + pub fn insert_status(&self, status: IrqStatus) { + self.inner.lock_irqsave().irqd_insert(status); } - pub fn irqd_clear(&self, status: IrqStatus) { + pub fn clear_status(&self, status: IrqStatus) { self.inner.lock_irqsave().irqd_clear(status); } + + pub fn clear_managed_shutdown(&self) { + self.inner + .lock_irqsave() + .state + .remove(IrqStatus::IRQD_MANAGED_SHUTDOWN); + } + + #[allow(dead_code)] + pub fn masked(&self) -> bool { + self.inner.lock_irqsave().state.masked() + } + + pub fn set_masked(&self) { + self.inner + .lock_irqsave() + .state + .insert(IrqStatus::IRQD_IRQ_MASKED); + } + + pub fn clear_masked(&self) { + self.clear_status(IrqStatus::IRQD_IRQ_MASKED); + } + + pub fn set_inprogress(&self) { + self.inner + .lock_irqsave() + .state + .insert(IrqStatus::IRQD_IRQ_INPROGRESS); + } + + pub fn clear_inprogress(&self) { + self.inner + .lock_irqsave() + .state + .remove(IrqStatus::IRQD_IRQ_INPROGRESS); + } + + pub fn disabled(&self) -> bool { + self.inner.lock_irqsave().state.disabled() + } + + #[allow(dead_code)] + pub fn set_disabled(&self) { + self.inner + .lock_irqsave() + .state + .insert(IrqStatus::IRQD_IRQ_DISABLED); + } + + pub fn clear_disabled(&self) { + self.clear_status(IrqStatus::IRQD_IRQ_DISABLED); + } + + pub fn status(&self) -> IrqStatus { + self.inner.lock_irqsave().state + } + + pub fn trigger_type(&self) -> IrqLineStatus { + self.inner.lock_irqsave().state.trigger_type() + } + + pub fn set_trigger_type(&self, trigger: IrqLineStatus) { + self.inner.lock_irqsave().state.set_trigger_type(trigger); + } + + pub fn set_started(&self) { + self.inner + .lock_irqsave() + .state + .insert(IrqStatus::IRQD_IRQ_STARTED); + } + + pub fn affinity(&self) -> CpuMask { + self.inner.lock_irqsave().affinity.clone() + } + + pub fn set_affinity(&self, affinity: CpuMask) { + self.inner.lock_irqsave().affinity = affinity; + } } #[allow(dead_code)] @@ -145,11 +298,11 @@ struct InnerIrqCommonData { /// per-IRQ data for the irq_chip methods handler_data: Option>, msi_desc: Option>, - // todo: affinity + affinity: CpuMask, } impl InnerIrqCommonData { - pub fn irqd_set(&mut self, status: IrqStatus) { + pub fn irqd_insert(&mut self, status: IrqStatus) { self.state.insert(status); } @@ -158,7 +311,8 @@ impl InnerIrqCommonData { } } -pub trait IrqHandlerData: Send + Sync + Any + Debug {} +/// 中断处理函数传入的数据 +pub trait IrqHandlerData: Send + Sync + Any + Debug + CastFromSync {} bitflags! { /// 中断线状态 @@ -219,12 +373,45 @@ bitflags! { +} + +impl IrqLineStatus { + pub const fn trigger_bits(&self) -> u32 { + self.bits & Self::IRQ_TYPE_SENSE_MASK.bits + } + + pub fn trigger_type(&self) -> Self { + *self & Self::IRQ_TYPE_SENSE_MASK + } + + pub fn is_level_type(&self) -> bool { + self.contains(Self::IRQ_LEVEL) + } + + /// 是否为高电平触发 + /// + /// ## 返回 + /// + /// - 如果不是电平触发类型,则返回None + /// - 如果是电平触发类型,则返回Some(bool),当为true时表示高电平触发 + pub fn is_level_high(&self) -> Option { + if !self.is_level_type() { + return None; + } + return Some(self.contains(Self::IRQ_TYPE_LEVEL_HIGH)); + } } bitflags! { /// 中断状态(存储在IrqCommonData) /// /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irq.h#227 pub struct IrqStatus: u32 { + const IRQD_TRIGGER_NONE = IrqLineStatus::IRQ_TYPE_NONE.bits(); + const IRQD_TRIGGER_RISING = IrqLineStatus::IRQ_TYPE_EDGE_RISING.bits(); + const IRQD_TRIGGER_FALLING = IrqLineStatus::IRQ_TYPE_EDGE_FALLING.bits(); + const IRQD_TRIGGER_HIGH = IrqLineStatus::IRQ_TYPE_LEVEL_HIGH.bits(); + const IRQD_TRIGGER_LOW = IrqLineStatus::IRQ_TYPE_LEVEL_LOW.bits(); + /// 触发类型位的掩码 const IRQD_TRIGGER_MASK = 0xf; /// 亲和性设置待处理 @@ -261,7 +448,7 @@ bitflags! { const IRQD_MANAGED_SHUTDOWN = 1 << 23; /// IRQ只允许单个亲和性目标 const IRQD_SINGLE_TARGET = 1 << 24; - /// 预期的触发器已设置 + /// 默认的触发器已设置 const IRQD_DEFAULT_TRIGGER_SET = 1 << 25; /// 可以使用保留模式 const IRQD_CAN_RESERVE = 1 << 26; @@ -294,6 +481,14 @@ impl IrqStatus { self.contains(Self::IRQD_AFFINITY_SET) } + pub fn masked(&self) -> bool { + self.contains(Self::IRQD_IRQ_MASKED) + } + + pub fn disabled(&self) -> bool { + self.contains(Self::IRQD_IRQ_DISABLED) + } + pub fn mark_affinity_set(&mut self) { self.insert(Self::IRQD_AFFINITY_SET); } @@ -353,14 +548,6 @@ impl IrqStatus { self.contains(Self::IRQD_MOVE_PCNTXT) } - pub const fn is_irq_disabled(&self) -> bool { - self.contains(Self::IRQD_IRQ_DISABLED) - } - - pub const fn is_irq_masked(&self) -> bool { - self.contains(Self::IRQD_IRQ_MASKED) - } - pub const fn is_irq_in_progress(&self) -> bool { self.contains(Self::IRQD_IRQ_INPROGRESS) } @@ -377,7 +564,7 @@ impl IrqStatus { self.insert(Self::IRQD_FORWARDED_TO_VCPU); } - pub const fn is_affinity_managed(&self) -> bool { + pub const fn affinity_managed(&self) -> bool { self.contains(Self::IRQD_AFFINITY_MANAGED) } @@ -432,4 +619,8 @@ impl IrqStatus { pub const fn is_affinity_on_activate(&self) -> bool { self.contains(Self::IRQD_AFFINITY_ON_ACTIVATE) } + + pub const fn started(&self) -> bool { + self.contains(Self::IRQD_IRQ_STARTED) + } } diff --git a/kernel/src/exception/irqdesc.rs b/kernel/src/exception/irqdesc.rs index 067c20d9..7209f584 100644 --- a/kernel/src/exception/irqdesc.rs +++ b/kernel/src/exception/irqdesc.rs @@ -1,4 +1,8 @@ -use core::{any::Any, fmt::Debug}; +use core::{ + any::Any, + fmt::Debug, + sync::atomic::{AtomicI64, Ordering}, +}; use alloc::{ collections::{btree_map, BTreeMap}, @@ -9,7 +13,7 @@ use alloc::{ use system_error::SystemError; use crate::{ - arch::CurrentIrqArch, + arch::{interrupt::TrapFrame, CurrentIrqArch}, driver::base::{ device::DeviceId, kobject::{KObjType, KObject, KObjectState, LockedKObjectState}, @@ -17,23 +21,48 @@ use crate::{ }, filesystem::kernfs::KernFSInode, libs::{ - rwlock::{RwLockReadGuard, RwLockWriteGuard}, + mutex::{Mutex, MutexGuard}, + rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}, spinlock::{SpinLock, SpinLockGuard}, }, process::ProcessControlBlock, + sched::completion::Completion, }; use super::{ dummychip::no_irq_chip, handle::bad_irq_handler, - irqdata::{IrqCommonData, IrqData, IrqStatus}, + irqdata::{IrqCommonData, IrqData, IrqHandlerData, IrqLineStatus, IrqStatus}, sysfs::{irq_sysfs_del, IrqKObjType}, HardwareIrqNumber, InterruptArch, IrqNumber, }; /// 中断流处理程序 -pub trait IrqFlowHandler: Debug + Send + Sync { - fn handle(&self, irq_desc: &Arc); +pub trait IrqFlowHandler: Debug + Send + Sync + Any { + fn handle(&self, irq_desc: &Arc, trap_frame: &mut TrapFrame); +} + +/// 中断处理程序 +pub trait IrqHandler: Debug + Send + Sync + Any { + fn handle( + &self, + irq: IrqNumber, + static_data: Option<&dyn IrqHandlerData>, + dynamic_data: Option>, + ) -> Result; +} + +/// 中断处理函数返回值 +/// +/// 用于指示中断处理函数是否处理了中断 +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum IrqReturn { + /// 中断未被处理 + NotHandled, + /// 中断已被处理 + Handled, + /// 中断已被处理,并且需要唤醒中断线程 + WakeThread, } /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irqdesc.h#55 @@ -41,9 +70,12 @@ pub trait IrqFlowHandler: Debug + Send + Sync { pub struct IrqDesc { inner: SpinLock, - handler: SpinLock>, - + handler: RwLock>, + /// 一个用于串行化 request_irq()和free_irq() 的互斥锁 + request_mutex: Mutex<()>, kobj_state: LockedKObjectState, + /// 当前描述符内正在运行的中断线程数 + threads_active: AtomicI64, } impl IrqDesc { @@ -59,13 +91,14 @@ impl IrqDesc { )); irq_data.irqd_set(IrqStatus::IRQD_IRQ_DISABLED); - common_data.irqd_set(IrqStatus::IRQD_IRQ_MASKED); + common_data.insert_status(IrqStatus::IRQD_IRQ_MASKED); let irq_desc = IrqDesc { inner: SpinLock::new(InnerIrqDesc { common_data, irq_data, desc_internal_state: IrqDescState::empty(), + line_status: IrqLineStatus::empty(), actions: Vec::new(), name, parent_irq: None, @@ -75,8 +108,10 @@ impl IrqDesc { kset: None, parent_kobj: None, }), - handler: SpinLock::new(None), + request_mutex: Mutex::new(()), + handler: RwLock::new(None), kobj_state: LockedKObjectState::new(Some(KObjectState::INITIALIZED)), + threads_active: AtomicI64::new(0), }; irq_desc.set_handler(bad_irq_handler()); @@ -85,12 +120,36 @@ impl IrqDesc { return Arc::new(irq_desc); } - pub fn set_handler(&self, handler: &'static dyn IrqFlowHandler) { - let mut guard = self.handler.lock_irqsave(); - *guard = Some(handler); + /// 返回当前活跃的中断线程数量 + #[allow(dead_code)] + pub fn threads_active(&self) -> i64 { + self.threads_active.load(Ordering::SeqCst) } - fn inner(&self) -> SpinLockGuard { + /// 增加当前活跃的中断线程数量, 返回增加前的值 + pub fn inc_threads_active(&self) -> i64 { + self.threads_active.fetch_add(1, Ordering::SeqCst) + } + + /// 减少当前活跃的中断线程数量, 返回减少前的值 + #[allow(dead_code)] + pub fn dec_threads_active(&self) -> i64 { + self.threads_active.fetch_sub(1, Ordering::SeqCst) + } + + pub fn set_handler(&self, handler: &'static dyn IrqFlowHandler) { + self.chip_bus_lock(); + let mut guard = self.handler.write_irqsave(); + *guard = Some(handler); + self.chip_bus_sync_unlock(); + } + + pub fn handler(&self) -> Option<&'static dyn IrqFlowHandler> { + let guard = self.handler.read_irqsave(); + *guard + } + + pub fn inner(&self) -> SpinLockGuard { self.inner.lock_irqsave() } @@ -98,6 +157,11 @@ impl IrqDesc { self.inner().actions.clone() } + /// 对中断请求过程加锁 + pub fn request_mutex_lock(&self) -> MutexGuard<()> { + self.request_mutex.lock() + } + pub fn irq(&self) -> IrqNumber { self.inner().irq_data.irq() } @@ -133,11 +197,115 @@ impl IrqDesc { pub fn name(&self) -> Option { self.inner().name.clone() } + + pub fn can_request(&self) -> bool { + self.inner().can_request() + } + + #[allow(dead_code)] + pub fn set_norequest(&self) { + self.inner().set_norequest(); + } + + #[allow(dead_code)] + pub fn clear_norequest(&self) { + self.inner().clear_norequest(); + } + + pub fn nested_thread(&self) -> bool { + self.inner().nested_thread() + } + + /// 中断是否可以线程化 + pub fn can_thread(&self) -> bool { + !self + .inner() + .line_status + .contains(IrqLineStatus::IRQ_NOTHREAD) + } + + pub fn chip_bus_lock(&self) { + let irq_data = self.inner().irq_data.clone(); + irq_data + .chip_info_read_irqsave() + .chip() + .irq_bus_lock(&irq_data) + .ok(); + } + + /// 同步释放低速总线锁 + /// + /// ## 锁 + /// + /// 进入此函数时,必须持有低速总线锁,并且desc的inner锁和irqdata的inner锁 + /// 必须已经释放。否则将死锁。 + pub fn chip_bus_sync_unlock(&self) { + let irq_data = self.inner().irq_data.clone(); + irq_data + .chip_info_write_irqsave() + .chip() + .irq_bus_sync_unlock(&irq_data) + .ok(); + } + + pub fn modify_status(&self, clear: IrqLineStatus, set: IrqLineStatus) { + let mut desc_guard = self.inner(); + desc_guard.line_status.remove(clear); + desc_guard.line_status.insert(set); + + let mut trigger = desc_guard.common_data().trigger_type(); + + desc_guard.common_data().clear_status( + IrqStatus::IRQD_NO_BALANCING + | IrqStatus::IRQD_PER_CPU + | IrqStatus::IRQD_TRIGGER_MASK + | IrqStatus::IRQD_LEVEL + | IrqStatus::IRQD_MOVE_PCNTXT, + ); + + if desc_guard + .line_status + .contains(IrqLineStatus::IRQ_NO_BALANCING) + { + desc_guard + .common_data() + .insert_status(IrqStatus::IRQD_NO_BALANCING); + } + + if desc_guard.line_status.contains(IrqLineStatus::IRQ_PER_CPU) { + desc_guard + .common_data() + .insert_status(IrqStatus::IRQD_PER_CPU); + } + + if desc_guard + .line_status + .contains(IrqLineStatus::IRQ_MOVE_PCNTXT) + { + desc_guard + .common_data() + .insert_status(IrqStatus::IRQD_MOVE_PCNTXT); + } + + if desc_guard.line_status.is_level_type() { + desc_guard + .common_data() + .insert_status(IrqStatus::IRQD_LEVEL); + } + + let tmp = desc_guard.line_status.trigger_type(); + + if tmp != IrqLineStatus::IRQ_TYPE_NONE { + trigger = tmp; + } + + desc_guard.common_data().set_trigger_type(trigger); + } } #[allow(dead_code)] #[derive(Debug)] -struct InnerIrqDesc { +pub struct InnerIrqDesc { /// per irq and chip data passed down to chip functions common_data: Arc, irq_data: Arc, @@ -149,10 +317,134 @@ struct InnerIrqDesc { /// nested wake enables wake_depth: u32, desc_internal_state: IrqDescState, + /// 中断线的状态 + line_status: IrqLineStatus, kern_inode: Option>, kset: Option>, parent_kobj: Option>, + // wait_for_threads: EventWaitQueue +} + +impl InnerIrqDesc { + pub fn name(&self) -> Option<&String> { + self.name.as_ref() + } + + pub fn can_request(&self) -> bool { + !self.line_status.contains(IrqLineStatus::IRQ_NOREQUEST) + } + + #[allow(dead_code)] + pub fn set_norequest(&mut self) { + self.line_status.insert(IrqLineStatus::IRQ_NOREQUEST); + } + + #[allow(dead_code)] + pub fn clear_norequest(&mut self) { + self.line_status.remove(IrqLineStatus::IRQ_NOREQUEST); + } + + pub fn nested_thread(&self) -> bool { + self.line_status.contains(IrqLineStatus::IRQ_NESTED_THREAD) + } + + pub fn line_status_set_per_cpu(&mut self) { + self.line_status.insert(IrqLineStatus::IRQ_PER_CPU); + } + + #[allow(dead_code)] + pub fn line_status_clear_per_cpu(&mut self) { + self.line_status.remove(IrqLineStatus::IRQ_PER_CPU); + } + + #[allow(dead_code)] + pub fn line_status(&self) -> &IrqLineStatus { + &self.line_status + } + + pub fn line_status_set_no_debug(&mut self) { + self.line_status.insert(IrqLineStatus::IRQ_NO_BALANCING); + } + + #[allow(dead_code)] + pub fn line_status_clear_no_debug(&mut self) { + self.line_status.remove(IrqLineStatus::IRQ_NO_BALANCING); + } + + pub fn can_autoenable(&self) -> bool { + !self.line_status.contains(IrqLineStatus::IRQ_NOAUTOEN) + } + + pub fn can_thread(&self) -> bool { + !self.line_status.contains(IrqLineStatus::IRQ_NOTHREAD) + } + + /// 中断是否可以设置CPU亲和性 + pub fn can_set_affinity(&self) -> bool { + if self.common_data.status().can_balance() == false + || self + .irq_data() + .chip_info_read_irqsave() + .chip() + .can_set_affinity() + == false + { + return false; + } + + return true; + } + + pub fn actions(&self) -> &Vec> { + &self.actions + } + + pub fn add_action(&mut self, action: Arc) { + self.actions.push(action); + } + + pub fn internal_state(&self) -> &IrqDescState { + &self.desc_internal_state + } + + pub(super) fn internal_state_mut(&mut self) -> &mut IrqDescState { + &mut self.desc_internal_state + } + + pub fn irq_data(&self) -> &Arc { + &self.irq_data + } + + pub fn common_data(&self) -> &Arc { + &self.common_data + } + + pub fn depth(&self) -> u32 { + self.depth + } + + pub fn wake_depth(&self) -> u32 { + self.wake_depth + } + + pub fn set_depth(&mut self, depth: u32) { + self.depth = depth; + } + + pub fn set_trigger_type(&mut self, trigger: IrqLineStatus) { + self.line_status.remove(IrqLineStatus::IRQ_TYPE_SENSE_MASK); + self.line_status + .insert(trigger & IrqLineStatus::IRQ_TYPE_SENSE_MASK); + } + + pub fn clear_level(&mut self) { + self.line_status.remove(IrqLineStatus::IRQ_LEVEL); + } + + pub fn set_level(&mut self) { + self.line_status.insert(IrqLineStatus::IRQ_LEVEL); + } } impl KObject for IrqDesc { @@ -211,7 +503,7 @@ impl KObject for IrqDesc { bitflags! { /// Bit masks for desc->desc_internal_state - struct IrqDescState: u32 { + pub struct IrqDescState: u32 { /// autodetection in progress const IRQS_AUTODETECT = 0x00000001; /// was disabled due to spurious interrupt detection @@ -241,6 +533,8 @@ bitflags! { #[derive(Debug)] pub struct IrqAction { inner: SpinLock, + /// 用于等待线程被创建的完成量 + thread_completion: Completion, } impl IrqAction { @@ -248,42 +542,45 @@ impl IrqAction { pub fn new( irq: IrqNumber, name: String, - handler: Option<&'static dyn IrqFlowHandler>, + handler: Option<&'static dyn IrqHandler>, + thread_fn: Option<&'static dyn IrqHandler>, ) -> Arc { - let action = IrqAction { + let action: IrqAction = IrqAction { inner: SpinLock::new(InnerIrqAction { dev_id: None, handler, - thread_fn: None, + thread_fn, thread: None, secondary: None, irq, flags: IrqHandleFlags::empty(), name, + thread_flags: ThreadedHandlerFlags::empty(), }), + thread_completion: Completion::new(), }; return Arc::new(action); } - pub fn name(&self) -> String { - self.inner().name.clone() + pub fn inner(&self) -> SpinLockGuard { + self.inner.lock_irqsave() } - fn inner(&self) -> SpinLockGuard { - self.inner.lock_irqsave() + pub fn thread_completion(&self) -> &Completion { + &self.thread_completion } } #[allow(dead_code)] #[derive(Debug)] -struct InnerIrqAction { +pub struct InnerIrqAction { /// cookie to identify the device - dev_id: Option, + dev_id: Option>, /// 中断处理程序 - handler: Option<&'static dyn IrqFlowHandler>, + handler: Option<&'static dyn IrqHandler>, /// interrupt handler function for threaded interrupts - thread_fn: Option<&'static dyn IrqFlowHandler>, + thread_fn: Option<&'static dyn IrqHandler>, /// thread pointer for threaded interrupts thread: Option>, /// pointer to secondary irqaction (force threading) @@ -291,14 +588,122 @@ struct InnerIrqAction { /// 中断号 irq: IrqNumber, flags: IrqHandleFlags, + /// 中断线程的标志 + thread_flags: ThreadedHandlerFlags, /// name of the device name: String, } +impl InnerIrqAction { + pub fn dev_id(&self) -> &Option> { + &self.dev_id + } + + pub fn dev_id_mut(&mut self) -> &mut Option> { + &mut self.dev_id + } + + pub fn handler(&self) -> Option<&'static dyn IrqHandler> { + self.handler + } + + pub fn set_handler(&mut self, handler: Option<&'static dyn IrqHandler>) { + self.handler = handler; + } + + pub fn thread_fn(&self) -> Option<&'static dyn IrqHandler> { + self.thread_fn + } + + pub fn thread(&self) -> Option> { + self.thread.clone() + } + + pub fn set_thread(&mut self, thread: Option>) { + self.thread = thread; + } + + #[allow(dead_code)] + pub fn thread_flags(&self) -> &ThreadedHandlerFlags { + &self.thread_flags + } + + pub fn thread_flags_mut(&mut self) -> &mut ThreadedHandlerFlags { + &mut self.thread_flags + } + + pub fn secondary(&self) -> Option> { + self.secondary.clone() + } + + #[allow(dead_code)] + pub fn irq(&self) -> IrqNumber { + self.irq + } + + #[allow(dead_code)] + pub fn set_irq(&mut self, irq: IrqNumber) { + self.irq = irq; + } + + pub fn flags(&self) -> &IrqHandleFlags { + &self.flags + } + + pub fn flags_mut(&mut self) -> &mut IrqHandleFlags { + &mut self.flags + } + + pub fn name(&self) -> &String { + &self.name + } +} + +bitflags! { + /// 这些标志由线程处理程序使用 + pub struct ThreadedHandlerFlags: u32 { + /// IRQTF_RUNTHREAD - 表示应运行中断处理程序线程 + const IRQTF_RUNTHREAD = 1 << 0; + /// IRQTF_WARNED - 已打印警告 "IRQ_WAKE_THREAD w/o thread_fn" + const IRQTF_WARNED = 1 << 1; + /// IRQTF_AFFINITY - 请求irq线程调整亲和性 + const IRQTF_AFFINITY = 1 << 2; + /// IRQTF_FORCED_THREAD - irq操作被强制线程化 + const IRQTF_FORCED_THREAD = 1 << 3; + /// IRQTF_READY - 表示irq线程已准备就绪 + const IRQTF_READY = 1 << 4; + } +} + +/// Implements the `ThreadedHandlerFlags` structure. +impl ThreadedHandlerFlags { + /// 在 `ThreadedHandlerFlags` 结构中测试并设置特定的位。 + /// + /// # 参数 + /// + /// * `bit` - 要测试并设置的位。 + /// + /// # 返回 + /// + /// 如果操作前该位已被设置,则返回 `true`,否则返回 `false`。 + pub fn test_and_set_bit(&mut self, bit: ThreadedHandlerFlags) -> bool { + let res = (self.bits & bit.bits) != 0; + self.bits |= bit.bits; + return res; + } +} + // 定义IrqFlags位标志 bitflags! { /// 这些标志仅由内核在中断处理例程中使用。 pub struct IrqHandleFlags: u32 { + + const IRQF_TRIGGER_NONE = IrqLineStatus::IRQ_TYPE_NONE.bits(); + const IRQF_TRIGGER_RISING = IrqLineStatus::IRQ_TYPE_EDGE_RISING.bits(); + const IRQF_TRIGGER_FALLING = IrqLineStatus::IRQ_TYPE_EDGE_FALLING.bits(); + const IRQF_TRIGGER_HIGH = IrqLineStatus::IRQ_TYPE_LEVEL_HIGH.bits(); + const IRQF_TRIGGER_LOW = IrqLineStatus::IRQ_TYPE_LEVEL_LOW.bits(); + const IRQF_TRIGGER_MASK = Self::IRQF_TRIGGER_HIGH.bits | Self::IRQF_TRIGGER_LOW.bits | Self::IRQF_TRIGGER_RISING.bits | Self::IRQF_TRIGGER_FALLING.bits; /// IRQF_SHARED - 允许多个设备共享中断 const IRQF_SHARED = 0x00000080; /// IRQF_PROBE_SHARED - 当预期出现共享不匹配时,由调用者设置 @@ -331,6 +736,28 @@ bitflags! { } } +impl IrqHandleFlags { + /// 检查是否指定了触发类型 + #[inline(always)] + pub fn trigger_type_specified(&self) -> bool { + (self.bits & Self::IRQF_TRIGGER_MASK.bits) != 0 + } + + /// 插入触发类型 + pub fn insert_trigger_type(&mut self, trigger: IrqLineStatus) { + self.bits |= trigger.trigger_bits() & IrqHandleFlags::IRQF_TRIGGER_MASK.bits; + } + + #[allow(dead_code)] + pub fn remove_trigger_type(&mut self, trigger: IrqLineStatus) { + self.bits &= !(trigger.trigger_bits() & IrqHandleFlags::IRQF_TRIGGER_MASK.bits); + } + + pub fn trigger_type(&self) -> IrqLineStatus { + IrqLineStatus::from_bits_truncate(self.bits & IrqHandleFlags::IRQF_TRIGGER_MASK.bits) + } +} + #[inline(never)] pub(super) fn early_irq_init() -> Result<(), SystemError> { let irqcnt = CurrentIrqArch::probe_total_irq_num(); @@ -351,11 +778,11 @@ static mut IRQ_DESC_MANAGER: Option = None; /// 获取中断描述符管理器的引用 #[inline(always)] -pub(super) fn irq_desc_manager() -> &'static IrqDescManager { +pub fn irq_desc_manager() -> &'static IrqDescManager { return unsafe { IRQ_DESC_MANAGER.as_ref().unwrap() }; } -pub(super) struct IrqDescManager { +pub struct IrqDescManager { irq_descs: BTreeMap>, } @@ -367,7 +794,6 @@ impl IrqDescManager { } /// 查找中断描述符 - #[allow(dead_code)] pub fn lookup(&self, irq: IrqNumber) -> Option> { self.irq_descs.get(&irq).map(|desc| desc.clone()) } diff --git a/kernel/src/exception/irqdomain.rs b/kernel/src/exception/irqdomain.rs index 885aade9..59dc86f5 100644 --- a/kernel/src/exception/irqdomain.rs +++ b/kernel/src/exception/irqdomain.rs @@ -1,7 +1,7 @@ use core::fmt::Debug; use alloc::{ - string::String, + string::{String, ToString}, sync::{Arc, Weak}, vec::Vec, }; @@ -10,14 +10,274 @@ use system_error::SystemError; use crate::{ driver::{base::device::Device, open_firmware::device_node::DeviceNode}, + exception::{irqdata::IrqLineStatus, irqdesc::irq_desc_manager, manage::irq_manager}, libs::{rwlock::RwLock, spinlock::SpinLock}, }; use super::{ irqchip::{IrqChipGeneric, IrqGcFlags}, + irqdata::IrqData, HardwareIrqNumber, IrqNumber, }; +static mut IRQ_DOMAIN_MANAGER: Option> = None; + +/// 获取中断域管理器的引用 +#[inline(always)] +pub fn irq_domain_manager() -> &'static Arc { + unsafe { IRQ_DOMAIN_MANAGER.as_ref().unwrap() } +} + +pub(super) fn irq_domain_manager_init() { + unsafe { + IRQ_DOMAIN_MANAGER = Some(Arc::new(IrqDomainManager::new())); + } +} +/// 中断域管理器 +pub struct IrqDomainManager { + domains: SpinLock>>, + inner: RwLock, +} + +impl IrqDomainManager { + pub fn new() -> IrqDomainManager { + IrqDomainManager { + domains: SpinLock::new(Vec::new()), + inner: RwLock::new(InnerIrqDomainManager { + default_domain: None, + }), + } + } + + /// 创建一个新的irqdomain, 并将其添加到irqdomain管理器中 + /// + /// ## 参数 + /// + /// - `name` - 中断域的名字 + /// - `ops` - 中断域的操作 + /// - `first_irq` - 起始软件中断号 + /// - `first_hwirq` - 起始硬件中断号 + /// - `irq_size` - 中断号的数量 + /// + /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdomain.c?fi=__irq_domain_add#139 + pub fn create_and_add( + &self, + name: String, + ops: &'static dyn IrqDomainOps, + first_irq: IrqNumber, + first_hwirq: HardwareIrqNumber, + irq_size: u32, + ) -> Option> { + let domain = IrqDomain::new( + None, + Some(name), + ops, + IrqDomainFlags::NAME_ALLOCATED, + IrqDomainBusToken::Any, + first_irq + irq_size, + first_hwirq + irq_size, + )?; + + self.add_domain(domain.clone()); + + self.domain_associate_many(&domain, first_irq, first_hwirq, irq_size); + + return Some(domain); + } + + fn add_domain(&self, domain: Arc) { + self.domains.lock_irqsave().push(domain); + } + + #[allow(dead_code)] + pub fn remove_domain(&self, domain: &Arc) { + let mut domains = self.domains.lock_irqsave(); + let index = domains + .iter() + .position(|x| Arc::ptr_eq(x, domain)) + .expect("domain not found"); + domains.remove(index); + } + + /// 获取默认的中断域 + #[allow(dead_code)] + pub fn default_domain(&self) -> Option> { + self.inner.read().default_domain.clone() + } + + /// 设置默认的中断域 + /// + /// 在创建IRQ映射的时候,如果没有指定中断域,就会使用默认的中断域 + pub fn set_default_domain(&self, domain: Arc) { + self.inner.write_irqsave().default_domain = Some(domain); + } + + /// 将指定范围的硬件中断号与软件中断号一一对应的关联起来 + /// + /// ## 参数 + /// + /// - `domain` - 中断域 + /// - `first_irq` - 起始软件中断号 + /// - `first_hwirq` - 起始硬件中断号 + /// - `count` - 数量 + pub fn domain_associate_many( + &self, + domain: &Arc, + first_irq: IrqNumber, + first_hwirq: HardwareIrqNumber, + count: u32, + ) { + for i in 0..count { + if let Err(e) = self.domain_associate(domain, first_irq + i, first_hwirq + i) { + kwarn!("domain associate failed: {:?}, domain '{:?}' didn't like hwirq {} to virq {} mapping.", e, domain.name(), (first_hwirq + i).data(), (first_irq + i).data()); + } + } + } + + /// 将一个硬件中断号与一个软件中断号关联起来 + /// + /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/irqdomain.c#562 + pub fn domain_associate( + &self, + domain: &Arc, + irq: IrqNumber, + hwirq: HardwareIrqNumber, + ) -> Result<(), SystemError> { + if hwirq >= domain.revmap.read_irqsave().hwirq_max { + kwarn!( + "hwirq {} is out of range for domain {:?}", + hwirq.data(), + domain.name() + ); + return Err(SystemError::EINVAL); + } + let irq_data = irq_desc_manager() + .lookup(irq) + .ok_or_else(|| { + kwarn!("irq_desc not found for irq {}", irq.data()); + SystemError::EINVAL + })? + .irq_data(); + if irq_data.domain().is_some() { + kwarn!( + "irq {} is already associated with domain {:?}", + irq.data(), + irq_data.domain().unwrap().name() + ); + return Err(SystemError::EINVAL); + } + + let mut irq_data_guard = irq_data.inner(); + irq_data_guard.set_hwirq(hwirq); + irq_data_guard.set_domain(Some(domain.clone())); + drop(irq_data_guard); + let r = domain.ops.map(&domain, hwirq, irq); + if let Err(e) = r { + if e != SystemError::ENOSYS { + if e != SystemError::EPERM { + kinfo!("domain associate failed: {:?}, domain '{:?}' didn't like hwirq {} to virq {} mapping.", e, domain.name(), hwirq.data(), irq.data()); + } + let mut irq_data_guard = irq_data.inner(); + irq_data_guard.set_domain(None); + irq_data_guard.set_hwirq(HardwareIrqNumber::new(0)); + return Err(e); + } + } + + if domain.name().is_none() { + let chip = irq_data.chip_info_read_irqsave().chip(); + domain.set_name(chip.name().to_string()); + } + + self.irq_domain_set_mapping(&domain, hwirq, irq_data); + + irq_manager().irq_clear_status_flags(irq, IrqLineStatus::IRQ_NOREQUEST)?; + + return Ok(()); + } + + fn irq_domain_set_mapping( + &self, + domain: &Arc, + hwirq: HardwareIrqNumber, + irq_data: Arc, + ) { + if domain.no_map() { + return; + } + + domain.revmap.write_irqsave().insert(hwirq, irq_data); + } + /// 递归调用 domain_ops->activate 以激活中断 + /// + /// ## 参数 + /// + /// - irq_data: 与中断关联的最外层 irq_data + /// - reserve: 如果为true,则仅预留一个中断向量,而不是分配一个 + /// + /// 这是调用 domain_ops->activate 以编程中断控制器的第二步,以便中断实际上可以被传递。 + pub fn activate_irq(&self, irq_data: &Arc, reserve: bool) -> Result<(), SystemError> { + let mut r = Ok(()); + if !irq_data.common_data().status().is_activated() { + r = self.do_activate_irq(Some(irq_data.clone()), reserve); + } + + if !r.is_ok() { + irq_data.common_data().status().set_activated(); + } + + return r; + } + + #[inline(never)] + fn do_activate_irq( + &self, + irq_data: Option>, + reserve: bool, + ) -> Result<(), SystemError> { + let mut r = Ok(()); + + if irq_data.is_some() && irq_data.as_ref().unwrap().domain().is_some() { + let domain = irq_data.as_ref().unwrap().domain().unwrap(); + + let irq_data = irq_data.unwrap(); + + let parent_data = irq_data.parent_data().map(|x| x.upgrade()).flatten(); + if let Some(parent_data) = parent_data.clone() { + r = self.do_activate_irq(Some(parent_data), reserve); + } + + if r.is_err() { + let tmpr = domain.ops.activate(&domain, &irq_data, reserve); + if let Err(e) = tmpr { + if e != SystemError::ENOSYS && parent_data.is_some() { + self.do_deactivate_irq(parent_data); + } + } + } + } + + return r; + } + + fn do_deactivate_irq(&self, irq_data: Option>) { + if let Some(irq_data) = irq_data { + if let Some(domain) = irq_data.domain() { + domain.ops.deactivate(&domain, &irq_data); + let pp = irq_data.parent_data().map(|x| x.upgrade()).flatten(); + + if pp.is_some() { + self.do_deactivate_irq(pp); + } + } + } + } +} + +struct InnerIrqDomainManager { + default_domain: Option>, +} + /// 中断域 /// /// 用于把硬件中断号翻译为软件中断号的映射的对象 @@ -28,7 +288,7 @@ use super::{ pub struct IrqDomain { /// 中断域的名字 (二选一) name: Option<&'static str>, - allocated_name: Option, + allocated_name: SpinLock>, /// 中断域的操作 ops: &'static dyn IrqDomainOps, inner: SpinLock, @@ -63,6 +323,8 @@ impl IrqDomain { ops: &'static dyn IrqDomainOps, flags: IrqDomainFlags, bus_token: IrqDomainBusToken, + irq_max: IrqNumber, + hwirq_max: HardwareIrqNumber, ) -> Option> { if name.is_none() && allocated_name.is_none() { return None; @@ -70,7 +332,7 @@ impl IrqDomain { let x = IrqDomain { name, - allocated_name, + allocated_name: SpinLock::new(allocated_name), ops, inner: SpinLock::new(InnerIrqDomain { flags, @@ -82,20 +344,67 @@ impl IrqDomain { }), revmap: RwLock::new(IrqDomainRevMap { map: HashMap::new(), - hwirq_max: HardwareIrqNumber::new(0), + hwirq_max, + irq_max, }), }; return Some(Arc::new(x)); } + + /// 中断域是否不对中断号进行转换 + pub fn no_map(&self) -> bool { + self.inner + .lock_irqsave() + .flags + .contains(IrqDomainFlags::NO_MAP) + } + + #[allow(dead_code)] + fn set_hwirq_max(&self, hwirq_max: HardwareIrqNumber) { + self.revmap.write_irqsave().hwirq_max = hwirq_max; + } + + pub fn name(&self) -> Option { + if let Some(name) = self.name { + return Some(name.to_string()); + } + return self.allocated_name.lock_irqsave().clone(); + } + + pub fn set_name(&self, name: String) { + *self.allocated_name.lock_irqsave() = Some(name); + } + + /// The number of mapped interrupts + pub fn map_count(&self) -> u32 { + self.revmap.read().map.len() as u32 + } } /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/irqdomain.h#190 #[allow(dead_code)] #[derive(Debug)] struct IrqDomainRevMap { - map: HashMap, + map: HashMap>, hwirq_max: HardwareIrqNumber, + irq_max: IrqNumber, +} + +impl IrqDomainRevMap { + fn insert(&mut self, hwirq: HardwareIrqNumber, irq_data: Arc) { + self.map.insert(hwirq, irq_data); + } + + #[allow(dead_code)] + fn remove(&mut self, hwirq: HardwareIrqNumber) { + self.map.remove(&hwirq); + } + + #[allow(dead_code)] + fn lookup(&self, hwirq: HardwareIrqNumber) -> Option> { + self.map.get(&hwirq).cloned() + } } bitflags! { @@ -156,15 +465,30 @@ pub trait IrqDomainOps: Debug + Send + Sync { /// 创建或更新一个虚拟中断号与一个硬件中断号之间的映射。 /// 对于给定的映射,这只会被调用一次。 + /// + /// 如果没有实现这个方法,那么就会返回`ENOSYS` fn map( &self, - irq_domain: &Arc, - hwirq: HardwareIrqNumber, - virq: IrqNumber, - ) -> Result<(), SystemError>; + _irq_domain: &Arc, + _hwirq: HardwareIrqNumber, + _virq: IrqNumber, + ) -> Result<(), SystemError> { + Err(SystemError::ENOSYS) + } /// 删除一个虚拟中断号与一个硬件中断号之间的映射。 fn unmap(&self, irq_domain: &Arc, virq: IrqNumber); + + fn activate( + &self, + _domain: &Arc, + _irq_data: &Arc, + _reserve: bool, + ) -> Result<(), SystemError> { + Err(SystemError::ENOSYS) + } + + fn deactivate(&self, _domain: &Arc, _irq_data: &Arc) {} } #[allow(dead_code)] diff --git a/kernel/src/exception/manage.rs b/kernel/src/exception/manage.rs new file mode 100644 index 00000000..5ef22696 --- /dev/null +++ b/kernel/src/exception/manage.rs @@ -0,0 +1,1093 @@ +use core::ops::{BitXor, Deref, DerefMut}; + +use alloc::{string::String, sync::Arc}; + +use system_error::SystemError; + +use crate::{ + driver::base::device::DeviceId, + exception::{ + irqchip::IrqChipSetMaskResult, + irqdesc::{irq_desc_manager, InnerIrqDesc, IrqAction}, + }, + libs::{cpumask::CpuMask, spinlock::SpinLockGuard}, + process::{kthread::KernelThreadMechanism, ProcessManager}, + smp::cpu::ProcessorId, +}; + +use super::{ + dummychip::no_irq_chip, + irqchip::IrqChipFlags, + irqdata::{IrqData, IrqHandlerData, IrqLineStatus, IrqStatus}, + irqdesc::{InnerIrqAction, IrqDesc, IrqDescState, IrqHandleFlags, IrqHandler, IrqReturn}, + irqdomain::irq_domain_manager, + IrqNumber, +}; + +lazy_static! { + /// 默认的中断亲和性 + static ref IRQ_DEFAULT_AFFINITY: CpuMask = { + let mut mask = CpuMask::new(); + // 默认情况下,中断处理程序将在第一个处理器上运行 + mask.set(ProcessorId::new(0), true); + mask + }; +} + +pub fn irq_manager() -> &'static IrqManager { + &IrqManager +} + +/// 中断管理器 +pub struct IrqManager; + +impl IrqManager { + pub const IRQ_RESEND: bool = true; + #[allow(dead_code)] + pub const IRQ_NORESEND: bool = false; + #[allow(dead_code)] + pub const IRQ_START_FORCE: bool = true; + pub const IRQ_START_COND: bool = false; + + /// 在中断线上添加一个处理函数 + /// + /// ## 参数 + /// + /// - irq: 虚拟中断号(中断线号) + /// - name: 生成该中断的设备名称 + /// - handler: 中断处理函数 + /// - flags: 中断处理标志 + /// - dev_id: 一个用于标识设备的cookie + pub fn request_irq( + &self, + irq: IrqNumber, + name: String, + handler: &'static dyn IrqHandler, + flags: IrqHandleFlags, + dev_id: Option>, + ) -> Result<(), SystemError> { + return self.request_threaded_irq(irq, Some(handler), None, flags, name, dev_id); + } + + /// 在中断线上添加一个处理函数(可以是线程化的中断) + /// + /// ## 参数 + /// + /// - irq: 虚拟中断号 + /// - handler: 当中断发生时将被调用的函数,是 + /// 线程化中断的初级处理程序。如果handler为`None`并且thread_fn不为`None`, + /// 将安装默认的初级处理程序 + /// - thread_fn: 在中断处理程序线程中调用的函数. 如果为`None`,则不会创建irq线程 + /// - flags: 中断处理标志 + /// - IRQF_SHARED: 中断是共享的 + /// - IRQF_TRIGGER*: 指定中断触发方式 + /// - IRQF_ONESHOT: 在thread_fn中运行时,中断线被遮蔽 + /// - dev_name: 生成该中断的设备名称 + /// - dev_id: 一个用于标识设备的cookie + /// + /// ## 说明 + /// + /// 此调用分配中断资源并启用中断线和IRQ处理。 + /// 从这一点开始,您的处理程序函数可能会被调用。 + /// 因此,您必须确保首先初始化您的硬件, + /// 并确保以正确的顺序设置中断处理程序。 + /// + /// 如果您想为您的设备设置线程化中断处理程序 + /// 则需要提供@handler和@thread_fn。@handler仍然 + /// 在硬中断上下文中调用,并且必须检查 + /// 中断是否来自设备。如果是,它需要禁用设备上的中断 + /// 并返回IRQ_WAKE_THREAD,这将唤醒处理程序线程并运行 + /// @thread_fn。这种拆分处理程序设计是为了支持 + /// 共享中断。 + /// + /// dev_id必须是全局唯一的。通常使用设备数据结构的地址或者uuid + /// 作为cookie。由于处理程序接收这个值,因此使用它是有意义的。 + /// + /// 如果您的中断是共享的,您必须传递一个非NULL的dev_id + /// 因为当释放中断时需要它。 + pub fn request_threaded_irq( + &self, + irq: IrqNumber, + mut handler: Option<&'static dyn IrqHandler>, + thread_fn: Option<&'static dyn IrqHandler>, + flags: IrqHandleFlags, + dev_name: String, + dev_id: Option>, + ) -> Result<(), SystemError> { + if irq == IrqNumber::IRQ_NOTCONNECTED { + return Err(SystemError::ENOTCONN); + } + + // 逻辑检查:共享中断必须传入一个真正的设备ID, + // 否则后来我们将难以确定哪个中断是哪个(会搞乱中断释放逻辑等)。 + // 此外,共享中断与禁用自动使能不相符。 共享中断可能在仍然禁用时请求它,然后永远等待中断。 + // 另外,IRQF_COND_SUSPEND 仅适用于共享中断,并且它不能与 IRQF_NO_SUSPEND 同时设置。 + + if ((flags.contains(IrqHandleFlags::IRQF_SHARED)) && dev_id.is_none()) + || ((flags.contains(IrqHandleFlags::IRQF_SHARED)) + && (flags.contains(IrqHandleFlags::IRQF_NO_AUTOEN))) + || (!(flags.contains(IrqHandleFlags::IRQF_SHARED)) + && (flags.contains(IrqHandleFlags::IRQF_COND_SUSPEND))) + || ((flags.contains(IrqHandleFlags::IRQF_NO_SUSPEND)) + && (flags.contains(IrqHandleFlags::IRQF_COND_SUSPEND))) + { + return Err(SystemError::EINVAL); + } + let desc = irq_desc_manager().lookup(irq).ok_or(SystemError::EINVAL)?; + if !desc.can_request() { + kwarn!("desc {} can not request", desc.irq().data()); + return Err(SystemError::EINVAL); + } + + if handler.is_none() { + if thread_fn.is_none() { + // 不允许中断处理函数和线程处理函数都为空 + return Err(SystemError::EINVAL); + } + + // 如果中断处理函数为空,线程处理函数不为空,则使用默认的中断处理函数 + handler = Some(&DefaultPrimaryIrqHandler); + } + + let irqaction = IrqAction::new(irq, dev_name, handler, thread_fn); + + let mut action_guard = irqaction.inner(); + *action_guard.flags_mut() = flags; + *action_guard.dev_id_mut() = dev_id; + drop(action_guard); + + return self.inner_setup_irq(irq, irqaction, desc); + } + + /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/manage.c?r=&mo=59252&fi=2138#1497 + #[inline(never)] + fn inner_setup_irq( + &self, + irq: IrqNumber, + action: Arc, + desc: Arc, + ) -> Result<(), SystemError> { + // ==== 定义错误处理函数 ==== + let err_out_thread = + |e: SystemError, mut action_guard: SpinLockGuard<'_, InnerIrqAction>| -> SystemError { + if let Some(thread_pcb) = action_guard.thread() { + action_guard.set_thread(None); + KernelThreadMechanism::stop(&thread_pcb).ok(); + } + + if let Some(secondary) = action_guard.secondary() { + let mut secondary_guard = secondary.inner(); + if let Some(thread_pcb) = secondary_guard.thread() { + secondary_guard.set_thread(None); + KernelThreadMechanism::stop(&thread_pcb).ok(); + } + } + return e; + }; + + let err_out_bus_unlock = |e: SystemError, + desc: Arc, + req_mutex_guard: crate::libs::mutex::MutexGuard<'_, ()>, + action_guard: SpinLockGuard<'_, InnerIrqAction>| + -> SystemError { + desc.chip_bus_sync_unlock(); + drop(req_mutex_guard); + return err_out_thread(e, action_guard); + }; + + let err_out_unlock = |e: SystemError, + desc_guard: SpinLockGuard<'_, InnerIrqDesc>, + desc: Arc, + req_mutex_guard: crate::libs::mutex::MutexGuard<'_, ()>, + action_guard: SpinLockGuard<'_, InnerIrqAction>| + -> SystemError { + drop(desc_guard); + return err_out_bus_unlock(e, desc, req_mutex_guard, action_guard); + }; + + let err_out_mismatch = |old_action_guard: SpinLockGuard<'_, InnerIrqAction>, + desc_guard: SpinLockGuard<'_, InnerIrqDesc>, + action_guard: SpinLockGuard<'_, InnerIrqAction>, + desc: Arc, + req_mutex_guard: crate::libs::mutex::MutexGuard<'_, ()>| + -> SystemError { + if !action_guard + .flags() + .contains(IrqHandleFlags::IRQF_PROBE_SHARED) + { + kerror!("Flags mismatch for irq {} (name: {}, flags: {:?}). old action name: {}, old flags: {:?}", irq.data(), action_guard.name(), action_guard.flags(), old_action_guard.name(), old_action_guard.flags()); + } + return err_out_unlock( + SystemError::EBUSY, + desc_guard, + desc, + req_mutex_guard, + action_guard, + ); + }; + + // ===== 代码开始 ===== + + if Arc::ptr_eq( + &desc.irq_data().chip_info_read_irqsave().chip(), + &no_irq_chip(), + ) { + return Err(SystemError::ENOSYS); + } + + let mut action_guard = action.inner(); + if !action_guard.flags().trigger_type_specified() { + // 如果没有指定触发类型,则使用默认的触发类型 + action_guard + .flags_mut() + .insert_trigger_type(desc.irq_data().common_data().trigger_type()) + } + + let nested = desc.nested_thread(); + + if nested { + if action_guard.thread_fn().is_none() { + return Err(SystemError::EINVAL); + } + + action_guard.set_handler(Some(&IrqNestedPrimaryHandler)); + } else { + if desc.can_thread() { + self.setup_forced_threading(action_guard.deref_mut())?; + } + } + + // 如果具有中断线程处理程序,并且中断不是嵌套的,则设置中断线程 + if action_guard.thread_fn().is_some() && !nested { + self.setup_irq_thread(irq, action_guard.deref(), false)?; + + if let Some(secondary) = action_guard.secondary() { + let secondary_guard = secondary.inner(); + if let Err(e) = self.setup_irq_thread(irq, secondary_guard.deref(), true) { + return Err(err_out_thread(e, action_guard)); + } + } + } + + // Drivers are often written to work w/o knowledge about the + // underlying irq chip implementation, so a request for a + // threaded irq without a primary hard irq context handler + // requires the ONESHOT flag to be set. Some irq chips like + // MSI based interrupts are per se one shot safe. Check the + // chip flags, so we can avoid the unmask dance at the end of + // the threaded handler for those. + + if desc + .irq_data() + .chip_info_read_irqsave() + .chip() + .flags() + .contains(IrqChipFlags::IRQCHIP_ONESHOT_SAFE) + { + *action_guard.flags_mut() &= !IrqHandleFlags::IRQF_ONESHOT; + } + + // Protects against a concurrent __free_irq() call which might wait + // for synchronize_hardirq() to complete without holding the optional + // chip bus lock and desc->lock. Also protects against handing out + // a recycled oneshot thread_mask bit while it's still in use by + // its previous owner. + let req_mutex_guard = desc.request_mutex_lock(); + + // Acquire bus lock as the irq_request_resources() callback below + // might rely on the serialization or the magic power management + // functions which are abusing the irq_bus_lock() callback, + desc.chip_bus_lock(); + + // 如果当前中断线上还没有irqaction, 则先为中断线申请资源 + if desc.actions().is_empty() { + if let Err(e) = self.irq_request_resources(desc.clone()) { + kerror!( + "Failed to request resources for {} (irq {}) on irqchip {}, error {:?}", + action_guard.name(), + irq.data(), + desc.irq_data().chip_info_read_irqsave().chip().name(), + e + ); + return Err(err_out_bus_unlock( + e, + desc.clone(), + req_mutex_guard, + action_guard, + )); + } + } + + let mut desc_inner_guard: SpinLockGuard<'_, InnerIrqDesc> = desc.inner(); + + // 标记当前irq是否是共享的 + let mut irq_shared = false; + if desc_inner_guard.actions().is_empty() == false { + // 除非双方都同意并且是相同类型(级别、边沿、极性),否则不能共享中断。 + // 因此,两个标志字段都必须设置IRQF_SHARED,并且设置触发类型的位必须匹配。 + // 另外,所有各方都必须就ONESHOT达成一致。 + // NMI用途的中断线不能共享。 + if desc_inner_guard + .internal_state() + .contains(IrqDescState::IRQS_NMI) + { + kerror!( + "Invalid attempt to share NMI for {} (irq {}) on irqchip {}", + action_guard.name(), + irq.data(), + desc_inner_guard + .irq_data() + .chip_info_read_irqsave() + .chip() + .name() + ); + return Err(err_out_unlock( + SystemError::EINVAL, + desc_inner_guard, + desc.clone(), + req_mutex_guard, + action_guard, + )); + } + + let irq_data = desc_inner_guard.irq_data(); + + let old_trigger_type: super::irqdata::IrqLineStatus; + let status = irq_data.common_data().status(); + if status.trigger_type_was_set() { + old_trigger_type = status.trigger_type(); + } else { + old_trigger_type = action_guard.flags().trigger_type(); + irq_data.common_data().set_trigger_type(old_trigger_type); + } + + let old = &desc_inner_guard.actions()[0].clone(); + let old_guard = old.inner(); + + if ((old_guard + .flags() + .intersection(*action_guard.flags()) + .contains(IrqHandleFlags::IRQF_SHARED)) + == false) + || (old_trigger_type != (action_guard.flags().trigger_type())) + || ((old_guard.flags().bitxor(*action_guard.flags())) + .contains(IrqHandleFlags::IRQF_ONESHOT)) + { + return Err(err_out_mismatch( + old_guard, + desc_inner_guard, + action_guard, + desc.clone(), + req_mutex_guard, + )); + } + + // all handlers must agree on per-cpuness + if *old_guard.flags() & IrqHandleFlags::IRQF_PERCPU + != *action_guard.flags() & IrqHandleFlags::IRQF_PERCPU + { + return Err(err_out_mismatch( + old_guard, + desc_inner_guard, + action_guard, + desc.clone(), + req_mutex_guard, + )); + } + + irq_shared = true; + } + + if action_guard.flags().contains(IrqHandleFlags::IRQF_ONESHOT) { + // todo: oneshot + } else if action_guard.handler().is_some_and(|h| { + h.type_id() == (&DefaultPrimaryIrqHandler as &dyn IrqHandler).type_id() + }) && desc_inner_guard + .irq_data() + .chip_info_read_irqsave() + .chip() + .flags() + .contains(IrqChipFlags::IRQCHIP_ONESHOT_SAFE) + == false + { + // 请求中断时 hander = NULL,因此我们为其使用默认的主处理程序。 + // 但它没有设置ONESHOT标志。与电平触发中断结合时, + // 这是致命的,因为默认的主处理程序只是唤醒线程,然后重新启用 irq 线路, + // 但设备仍然保持电平中断生效。周而复始.... + // 虽然这对于边缘类型中断来说可行,但我们为了安全起见,不加条件地拒绝, + // 因为我们不能确定这个中断实际上具有什么类型。 + // 由于底层芯片实现可能会覆盖它们,所以类型标志并不可靠. + + kerror!( + "Requesting irq {} without a handler, and ONESHOT flags not set for irqaction: {}", + irq.data(), + action_guard.name() + ); + return Err(err_out_unlock( + SystemError::EINVAL, + desc_inner_guard, + desc.clone(), + req_mutex_guard, + action_guard, + )); + } + + // 第一次在当前irqdesc上注册中断处理函数 + if !irq_shared { + // 设置中断触发方式 + if action_guard.flags().trigger_type_specified() { + let trigger_type = action_guard.flags().trigger_type(); + if let Err(e) = + self.do_set_irq_trigger(desc.clone(), &mut desc_inner_guard, trigger_type) + { + return Err(err_out_unlock( + e, + desc_inner_guard, + desc.clone(), + req_mutex_guard, + action_guard, + )); + } + } + + // 激活中断。这种激活必须独立于IRQ_NOAUTOEN进行*desc_inner_guard.internal_state_mut() |= IrqDescState::IRQS_NOREQUEST;uest. + if let Err(e) = self.irq_activate(desc.clone(), &mut desc_inner_guard) { + return Err(err_out_unlock( + e, + desc_inner_guard, + desc.clone(), + req_mutex_guard, + action_guard, + )); + } + + *desc_inner_guard.internal_state_mut() &= !(IrqDescState::IRQS_AUTODETECT + | IrqDescState::IRQS_SPURIOUS_DISABLED + | IrqDescState::IRQS_ONESHOT + | IrqDescState::IRQS_WAITING); + desc_inner_guard + .common_data() + .clear_status(IrqStatus::IRQD_IRQ_INPROGRESS); + + if action_guard.flags().contains(IrqHandleFlags::IRQF_PERCPU) { + desc_inner_guard + .common_data() + .insert_status(IrqStatus::IRQD_PER_CPU); + desc_inner_guard.line_status_set_per_cpu(); + + if action_guard.flags().contains(IrqHandleFlags::IRQF_NO_DEBUG) { + desc_inner_guard.line_status_set_no_debug(); + } + } + + if action_guard.flags().contains(IrqHandleFlags::IRQF_ONESHOT) { + *desc_inner_guard.internal_state_mut() |= IrqDescState::IRQS_ONESHOT; + } + + // 如果有要求的话,则忽略IRQ的均衡。 + if action_guard + .flags() + .contains(IrqHandleFlags::IRQF_NOBALANCING) + { + todo!("IRQF_NO_BALANCING"); + } + + if !action_guard + .flags() + .contains(IrqHandleFlags::IRQF_NO_AUTOEN) + && desc_inner_guard.can_autoenable() + { + // 如果没有设置IRQF_NOAUTOEN,则自动使能中断 + self.irq_startup( + desc.clone(), + &mut desc_inner_guard, + Self::IRQ_RESEND, + Self::IRQ_START_COND, + ) + .ok(); + } else { + // 共享中断与禁用自动使能不太兼容。 + // 共享中断可能在它仍然被禁用时请求它,然后永远等待中断。 + + static mut WARNED: bool = false; + if action_guard.flags().contains(IrqHandleFlags::IRQF_SHARED) { + if unsafe { !WARNED } { + kwarn!( + "Shared interrupt {} for {} requested but not auto enabled", + irq.data(), + action_guard.name() + ); + unsafe { WARNED = true }; + } + } + + desc_inner_guard.set_depth(1); + } + } else if action_guard.flags().trigger_type_specified() { + let new_trigger_type = action_guard.flags().trigger_type(); + let old_trigger_type = desc_inner_guard.common_data().trigger_type(); + if new_trigger_type != old_trigger_type { + kwarn!("Irq {} uses trigger type: {old_trigger_type:?}, but requested trigger type: {new_trigger_type:?}.", irq.data()); + } + } + + // 在队列末尾添加新的irqaction + desc_inner_guard.add_action(action.clone()); + + // 检查我们是否曾经通过虚构的中断处理程序禁用过irq。重新启用它并再给它一次机会。 + if irq_shared + && desc_inner_guard + .internal_state() + .contains(IrqDescState::IRQS_SPURIOUS_DISABLED) + { + desc_inner_guard + .internal_state_mut() + .remove(IrqDescState::IRQS_SPURIOUS_DISABLED); + self.do_enable_irq(desc.clone(), &mut desc_inner_guard).ok(); + } + + drop(desc_inner_guard); + desc.chip_bus_sync_unlock(); + drop(req_mutex_guard); + + drop(action_guard); + self.wake_up_and_wait_for_irq_thread_ready(&desc, Some(action.clone())); + self.wake_up_and_wait_for_irq_thread_ready(&desc, action.inner().secondary()); + return Ok(()); + } + + /// 唤醒中断线程并等待中断线程准备好 + /// + /// ## 参数 + /// + /// - desc: 中断描述符 + /// - action: 要唤醒的中断处理函数 + /// + /// ## 锁 + /// + /// 进入当前函数时,`action`的锁需要被释放 + fn wake_up_and_wait_for_irq_thread_ready( + &self, + desc: &Arc, + action: Option>, + ) { + if action.is_none() { + return; + } + + let action = action.unwrap(); + + let action_guard = action.inner(); + if action_guard.thread().is_none() { + return; + } + + ProcessManager::wakeup(&action_guard.thread().unwrap()).ok(); + drop(action_guard); + action + .thread_completion() + .wait_for_completion() + .map_err(|e| { + kwarn!( + "Failed to wait for irq thread ready for {} (irq {:?}), error {:?}", + action.inner().name(), + desc.irq_data().irq(), + e + ); + }) + .ok(); + } + + pub(super) fn irq_activate( + &self, + _desc: Arc, + desc_inner_guard: &mut SpinLockGuard<'_, InnerIrqDesc>, + ) -> Result<(), SystemError> { + let irq_data = desc_inner_guard.irq_data(); + + if !desc_inner_guard.common_data().status().affinity_managed() { + return irq_domain_manager().activate_irq(irq_data, false); + } + + return Ok(()); + } + + /// 设置CPU亲和性并开启中断 + pub(super) fn irq_startup( + &self, + desc: Arc, + desc_inner_guard: &mut SpinLockGuard<'_, InnerIrqDesc>, + resend: bool, + force: bool, + ) -> Result<(), SystemError> { + let mut ret = Ok(()); + let irq_data = desc_inner_guard.irq_data().clone(); + let affinity = desc_inner_guard.common_data().affinity(); + desc_inner_guard.set_depth(0); + + if desc_inner_guard.common_data().status().started() { + self.irq_enable(desc_inner_guard); + } else { + match self.__irq_startup_managed(desc_inner_guard, &affinity, force) { + IrqStartupResult::Normal => { + if irq_data + .chip_info_read_irqsave() + .chip() + .flags() + .contains(IrqChipFlags::IRQCHIP_AFFINITY_PRE_STARTUP) + { + self.irq_setup_affinity(&desc, desc_inner_guard).ok(); + } + + ret = self.__irq_startup(desc_inner_guard); + + if !irq_data + .chip_info_read_irqsave() + .chip() + .flags() + .contains(IrqChipFlags::IRQCHIP_AFFINITY_PRE_STARTUP) + { + self.irq_setup_affinity(&desc, desc_inner_guard).ok(); + } + } + IrqStartupResult::Managed => { + self.irq_do_set_affinity(&irq_data, &desc_inner_guard, &affinity, false) + .ok(); + ret = self.__irq_startup(desc_inner_guard); + } + IrqStartupResult::Abort => { + desc_inner_guard + .common_data() + .insert_status(IrqStatus::IRQD_MANAGED_SHUTDOWN); + return Ok(()); + } + } + } + + if resend { + if let Err(e) = self.irq_check_and_resend(desc_inner_guard, false) { + kerror!( + "Failed to check and resend irq {}, error {:?}", + irq_data.irq().data(), + e + ); + } + } + + return ret; + } + + pub fn irq_enable(&self, desc_inner_guard: &SpinLockGuard<'_, InnerIrqDesc>) { + let common_data = desc_inner_guard.common_data(); + if !common_data.status().disabled() { + self.unmask_irq(desc_inner_guard); + } else { + common_data.clear_disabled(); + + let chip = desc_inner_guard.irq_data().chip_info_read_irqsave().chip(); + + if let Err(e) = chip.irq_enable(&desc_inner_guard.irq_data()) { + if e == SystemError::ENOSYS { + self.unmask_irq(desc_inner_guard); + } + kerror!( + "Failed to enable irq {} (name: {:?}), error {:?}", + desc_inner_guard.irq_data().irq().data(), + desc_inner_guard.name(), + e + ); + } else { + common_data.clear_masked(); + } + } + } + + /// 自动设置中断的CPU亲和性 + /// + /// + /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/manage.c#589 + pub fn irq_setup_affinity( + &self, + _desc: &Arc, + desc_inner_guard: &mut SpinLockGuard<'_, InnerIrqDesc>, + ) -> Result<(), SystemError> { + let common_data = desc_inner_guard.common_data(); + if !desc_inner_guard.can_set_affinity() { + return Ok(()); + } + + let mut to_set = IRQ_DEFAULT_AFFINITY.clone(); + if common_data.status().affinity_managed() + || common_data.status().contains(IrqStatus::IRQD_AFFINITY_SET) + { + // FIXME: 要判断affinity跟已上线的CPU是否有交集 + + let irq_aff = common_data.affinity(); + if irq_aff.is_empty() { + common_data.clear_status(IrqStatus::IRQD_AFFINITY_SET); + } else { + to_set = irq_aff; + } + } + + // FIXME: 求to_set和在线CPU的交集 + + return self.irq_do_set_affinity( + desc_inner_guard.irq_data(), + &desc_inner_guard, + &to_set, + false, + ); + } + + pub fn irq_do_set_affinity( + &self, + irq_data: &Arc, + desc_inner_guard: &SpinLockGuard<'_, InnerIrqDesc>, + cpumask: &CpuMask, + force: bool, + ) -> Result<(), SystemError> { + let chip = irq_data.chip_info_read_irqsave().chip(); + if !chip.can_set_affinity() { + return Err(SystemError::EINVAL); + } + + // todo: 处理CPU中断隔离相关的逻辑 + + let common_data = desc_inner_guard.common_data(); + let r; + if !force && !cpumask.is_empty() { + r = chip.irq_set_affinity(irq_data, &cpumask, force); + } else if force { + r = chip.irq_set_affinity(irq_data, &cpumask, force); + } else { + return Err(SystemError::EINVAL); + } + + let mut ret = Ok(()); + if let Ok(rs) = r { + match rs { + IrqChipSetMaskResult::SetMaskOk | IrqChipSetMaskResult::SetMaskOkDone => { + common_data.set_affinity(cpumask.clone()); + } + IrqChipSetMaskResult::SetMaskOkNoChange => { + + // irq_validate_effective_affinity(data); + // irq_set_thread_affinity(desc); + } + } + } else { + ret = Err(r.unwrap_err()); + } + + return ret; + } + + fn __irq_startup( + &self, + desc_inner_guard: &SpinLockGuard<'_, InnerIrqDesc>, + ) -> Result<(), SystemError> { + let common_data = desc_inner_guard.common_data(); + + if let Err(e) = desc_inner_guard + .irq_data() + .chip_info_read_irqsave() + .chip() + .irq_startup(desc_inner_guard.irq_data()) + { + if e == SystemError::ENOSYS { + self.irq_enable(desc_inner_guard); + } else { + return Err(e); + } + } else { + common_data.clear_disabled(); + common_data.clear_masked(); + } + + common_data.set_started(); + + return Ok(()); + } + + fn __irq_startup_managed( + &self, + desc_inner_guard: &SpinLockGuard<'_, InnerIrqDesc>, + _affinity: &CpuMask, + _force: bool, + ) -> IrqStartupResult { + let irq_data = desc_inner_guard.irq_data(); + let common_data = desc_inner_guard.common_data(); + + if !common_data.status().affinity_managed() { + return IrqStartupResult::Normal; + } + + common_data.clear_managed_shutdown(); + + /* + - 检查Affinity掩码是否包括所有的在线CPU。如果是,这意味着有代码试图在管理的中断上使用enable_irq(), + 这可能是非法的。在这种情况下,如果force不是真值,函数会返回IRQ_STARTUP_ABORT,表示中断处理应该被放弃。 + - 如果Affinity掩码中没有任何在线的CPU,那么中断请求是不可用的,因为没有任何CPU可以处理它。 + 在这种情况下,如果force不是真值,函数同样会返回IRQ_STARTUP_ABORT。 + - 如果以上条件都不满足,尝试激活中断,并将其设置为管理模式。这是通过调用 `irq_domain_manager().activate_irq()` 函数来实现的。 + 如果这个调用失败,表示有保留的资源无法访问,函数会返回IRQ_STARTUP_ABORT。 + - 如果一切顺利,函数会返回IRQ_STARTUP_MANAGED,表示中断已经被成功管理并激活。 + */ + + // if (cpumask_any_and(aff, cpu_online_mask) >= nr_cpu_ids) { + // /* + // * Catch code which fiddles with enable_irq() on a managed + // * and potentially shutdown IRQ. Chained interrupt + // * installment or irq auto probing should not happen on + // * managed irqs either. + // */ + // if (WARN_ON_ONCE(force)) + // return IRQ_STARTUP_ABORT; + // /* + // * The interrupt was requested, but there is no online CPU + // * in it's affinity mask. Put it into managed shutdown + // * state and let the cpu hotplug mechanism start it up once + // * a CPU in the mask becomes available. + // */ + // return IRQ_STARTUP_ABORT; + // } + + let r = irq_domain_manager().activate_irq(irq_data, false); + if r.is_err() { + return IrqStartupResult::Abort; + } + + return IrqStartupResult::Managed; + } + + pub fn do_enable_irq( + &self, + _desc: Arc, + _desc_inner_guard: &mut SpinLockGuard<'_, InnerIrqDesc>, + ) -> Result<(), SystemError> { + // https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/manage.c?r=&mo=59252&fi=2138#776 + todo!("do_enable_irq") + } + + #[inline(never)] + pub fn do_set_irq_trigger( + &self, + _desc: Arc, + desc_inner_guard: &mut SpinLockGuard<'_, InnerIrqDesc>, + mut trigger_type: IrqLineStatus, + ) -> Result<(), SystemError> { + let chip = desc_inner_guard.irq_data().chip_info_read_irqsave().chip(); + let mut to_unmask = false; + + if !chip.can_set_flow_type() { + // kdebug!( + // "No set_irq_type function for irq {}, chip {}", + // desc_inner_guard.irq_data().irq().data(), + // chip.name() + // ); + return Ok(()); + } + + if chip.flags().contains(IrqChipFlags::IRQCHIP_SET_TYPE_MASKED) { + if desc_inner_guard.common_data().status().masked() == false { + self.mask_irq(desc_inner_guard.irq_data()); + } + if desc_inner_guard.common_data().status().disabled() == false { + to_unmask = true; + } + } + + trigger_type &= IrqLineStatus::IRQ_TYPE_SENSE_MASK; + + let r = chip.irq_set_type(desc_inner_guard.irq_data(), trigger_type); + let ret; + if let Ok(rs) = r { + match rs { + IrqChipSetMaskResult::SetMaskOk | IrqChipSetMaskResult::SetMaskOkDone => { + let common_data = desc_inner_guard.common_data(); + common_data.clear_status(IrqStatus::IRQD_TRIGGER_MASK); + let mut irqstatus = IrqStatus::empty(); + irqstatus.set_trigger_type(trigger_type); + common_data.insert_status(irqstatus); + } + IrqChipSetMaskResult::SetMaskOkNoChange => { + let flags = desc_inner_guard.common_data().trigger_type(); + desc_inner_guard.set_trigger_type(flags); + desc_inner_guard + .common_data() + .clear_status(IrqStatus::IRQD_LEVEL); + desc_inner_guard.clear_level(); + + if (flags & IrqLineStatus::IRQ_TYPE_LEVEL_MASK).is_empty() == false { + desc_inner_guard.set_level(); + desc_inner_guard + .common_data() + .insert_status(IrqStatus::IRQD_LEVEL); + } + } + } + + ret = Ok(()); + } else { + kerror!( + "Failed to set irq {} trigger type to {:?} on irqchip {}, error {:?}", + desc_inner_guard.irq_data().irq().data(), + trigger_type, + chip.name(), + r + ); + + ret = Err(r.unwrap_err()); + } + + if to_unmask { + self.unmask_irq(desc_inner_guard); + } + return ret; + } + + fn irq_request_resources(&self, desc: Arc) -> Result<(), SystemError> { + let irq_data = desc.irq_data(); + let irq_chip = irq_data.chip_info_read_irqsave().chip(); + irq_chip.irq_request_resources(&irq_data) + } + + /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/manage.c?r=&mo=59252&fi=2138#1448 + fn setup_irq_thread( + &self, + _irq: IrqNumber, + _action: &InnerIrqAction, + _secondary: bool, + ) -> Result<(), SystemError> { + // if secondary { + // KernelThreadMechanism::create(func, name) + // } + + todo!("setup_irq_thread") + } + + fn setup_forced_threading(&self, _action: &mut InnerIrqAction) -> Result<(), SystemError> { + // todo: 处理强制线程化的逻辑,参考linux的`irq_setup_forced_threading()` + return Ok(()); + } + + pub fn irq_clear_status_flags( + &self, + irq: IrqNumber, + status: IrqLineStatus, + ) -> Result<(), SystemError> { + let desc = irq_desc_manager().lookup(irq).ok_or(SystemError::EINVAL)?; + desc.modify_status(status, IrqLineStatus::empty()); + return Ok(()); + } + + /// 屏蔽中断 + pub(super) fn mask_irq(&self, irq_data: &Arc) { + if irq_data.common_data().status().masked() { + return; + } + + let chip = irq_data.chip_info_read_irqsave().chip(); + let r = chip.irq_mask(irq_data); + + if r.is_ok() { + irq_data.common_data().set_masked(); + } + } + + /// 解除屏蔽中断 + pub(super) fn unmask_irq(&self, desc_inner_guard: &SpinLockGuard<'_, InnerIrqDesc>) { + if desc_inner_guard.common_data().status().masked() == false { + return; + } + + let r = desc_inner_guard + .irq_data() + .chip_info_read_irqsave() + .chip() + .irq_unmask(&desc_inner_guard.irq_data()); + + if let Err(e) = r { + if e != SystemError::ENOSYS { + kerror!( + "Failed to unmask irq {} on irqchip {}, error {:?}", + desc_inner_guard.irq_data().irq().data(), + desc_inner_guard + .irq_data() + .chip_info_read_irqsave() + .chip() + .name(), + e + ); + } + } else { + desc_inner_guard + .common_data() + .clear_status(IrqStatus::IRQD_IRQ_MASKED); + } + } + + /// 释放使用request_irq分配的中断 + /// + /// ## 参数 + /// + /// - irq: 要释放的中断线 + /// - dev_id: 要释放的设备身份 + /// + /// ## 返回 + /// + /// 返回传递给request_irq的devname参数 + /// + /// ## 说明 + /// + /// 移除一个中断处理程序。处理程序被移除,如果该中断线不再被任何驱动程序使用,则会被禁用。 + /// + /// 在共享IRQ的情况下,调用者必须确保在调用此功能之前,它在所驱动的卡上禁用了中断。 + /// + /// ## 注意 + /// + /// 此函数不可以在中断上下文中调用。 + pub fn free_irq(&self, _irq: IrqNumber, _dev_id: Option>) { + kwarn!("Unimplemented free_irq"); + } +} + +enum IrqStartupResult { + Normal, + Managed, + Abort, +} +/// 默认的初级中断处理函数 +/// +/// 该处理函数仅仅返回`WakeThread`,即唤醒中断线程 +#[derive(Debug)] +struct DefaultPrimaryIrqHandler; + +impl IrqHandler for DefaultPrimaryIrqHandler { + fn handle( + &self, + _irq: IrqNumber, + _static_data: Option<&dyn IrqHandlerData>, + _dynamic_data: Option>, + ) -> Result { + return Ok(IrqReturn::WakeThread); + } +} + +/// Primary handler for nested threaded interrupts. +/// Should never be called. +#[derive(Debug)] +struct IrqNestedPrimaryHandler; + +impl IrqHandler for IrqNestedPrimaryHandler { + fn handle( + &self, + irq: IrqNumber, + _static_data: Option<&dyn IrqHandlerData>, + _dynamic_data: Option>, + ) -> Result { + kwarn!("Primary handler called for nested irq {}", irq.data()); + return Ok(IrqReturn::NotHandled); + } +} diff --git a/kernel/src/exception/mod.rs b/kernel/src/exception/mod.rs index 90aa0d9b..a483fce3 100644 --- a/kernel/src/exception/mod.rs +++ b/kernel/src/exception/mod.rs @@ -1,3 +1,5 @@ +use core::ops::Add; + use system_error::SystemError; use crate::arch::CurrentIrqArch; @@ -10,7 +12,9 @@ pub mod irqchip; pub mod irqdata; pub mod irqdesc; pub mod irqdomain; +pub mod manage; pub mod msi; +mod resend; pub mod softirq; pub mod sysfs; @@ -100,6 +104,28 @@ impl Drop for IrqFlagsGuard { // 用于表示软件逻辑视角的中断号,全局唯一 int_like!(IrqNumber, u32); +impl IrqNumber { + /// 如果一个(PCI)设备中断没有被连接,我们将设置irqnumber为IRQ_NOTCONNECTED。 + /// 这导致request_irq()失败,返回-ENOTCONN,这样我们就可以区分这种情况和其他错误返回。 + pub const IRQ_NOTCONNECTED: IrqNumber = IrqNumber::new(u32::MAX); +} + // 硬件中断号 // 用于表示在某个IrqDomain中的中断号 int_like!(HardwareIrqNumber, u32); + +impl Add for HardwareIrqNumber { + type Output = HardwareIrqNumber; + + fn add(self, rhs: u32) -> HardwareIrqNumber { + HardwareIrqNumber::new(self.0 + rhs) + } +} + +impl Add for IrqNumber { + type Output = IrqNumber; + + fn add(self, rhs: u32) -> IrqNumber { + IrqNumber::new(self.0 + rhs) + } +} diff --git a/kernel/src/exception/msi.rs b/kernel/src/exception/msi.rs index 10f2ef5f..f521d117 100644 --- a/kernel/src/exception/msi.rs +++ b/kernel/src/exception/msi.rs @@ -51,6 +51,14 @@ impl MsiMsg { pub const fn address(&self) -> u64 { (self.address_hi as u64) << 32 | self.address_lo as u64 } + + pub const fn new_zeroed() -> Self { + MsiMsg { + address_lo: 0, + address_hi: 0, + data: 0, + } + } } #[allow(dead_code)] diff --git a/kernel/src/exception/resend.rs b/kernel/src/exception/resend.rs new file mode 100644 index 00000000..8089c294 --- /dev/null +++ b/kernel/src/exception/resend.rs @@ -0,0 +1,91 @@ +use system_error::SystemError; + +use crate::{exception::irqdesc::IrqDescState, libs::spinlock::SpinLockGuard}; + +use super::{irqdesc::InnerIrqDesc, manage::IrqManager}; + +impl IrqManager { + /// 检查状态并重发中断 + /// + /// ## 参数 + /// + /// - `desc_inner_guard`:中断描述符的锁 + /// - `inject`:是否注入中断 + pub(super) fn irq_check_and_resend( + &self, + desc_inner_guard: &mut SpinLockGuard<'_, InnerIrqDesc>, + inject: bool, + ) -> Result<(), SystemError> { + // https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/resend.c?fi=check_irq_resend#106 + + /* + * 我们不重新发送电平触发类型的中断。电平触发类型的中断在它们仍然活动时由硬件重新发送。 + * 清除PENDING bit,以避免suspend/resume过程中的混淆。 + */ + if desc_inner_guard + .common_data() + .trigger_type() + .is_level_type() + { + desc_inner_guard + .internal_state_mut() + .remove(IrqDescState::IRQS_PENDING); + return Err(SystemError::EINVAL); + } + + if desc_inner_guard + .internal_state() + .contains(IrqDescState::IRQS_REPLAY) + { + return Err(SystemError::EBUSY); + } + + if desc_inner_guard + .internal_state() + .contains(IrqDescState::IRQS_PENDING) + == false + && inject == false + { + return Ok(()); + } + + desc_inner_guard + .internal_state_mut() + .remove(IrqDescState::IRQS_PENDING); + + let mut ret = Ok(()); + if self.try_retrigger(desc_inner_guard).is_err() { + // todo: 支持发送到tasklet + ret = Err(SystemError::EINVAL); + } + + if ret.is_ok() { + desc_inner_guard + .internal_state_mut() + .insert(IrqDescState::IRQS_REPLAY); + } + + return ret; + } + + fn try_retrigger( + &self, + desc_inner_guard: &SpinLockGuard<'_, InnerIrqDesc>, + ) -> Result<(), SystemError> { + if let Err(e) = desc_inner_guard + .irq_data() + .chip_info_read_irqsave() + .chip() + .retrigger(desc_inner_guard.irq_data()) + { + if e != SystemError::ENOSYS { + return Err(e); + } + } else { + return Ok(()); + } + + // 当前中断控制器不支持重发中断,从父中断控制器重发 + return self.irq_chip_retrigger_hierarchy(desc_inner_guard.irq_data()); + } +} diff --git a/kernel/src/exception/softirq.h b/kernel/src/exception/softirq.h deleted file mode 100644 index dc61e862..00000000 --- a/kernel/src/exception/softirq.h +++ /dev/null @@ -1,25 +0,0 @@ -/** - * @file softirq.h - * @author fslongjin (longjin@RinGoTek.cn) - * @brief 软中断 - * @version 0.1 - * @date 2022-04-08 - * - * @copyright Copyright (c) 2022 - * - */ -#pragma once - -#include - -// ==================implementation with rust=================== -extern void rs_softirq_init(); -extern void rs_raise_softirq(uint32_t sirq_num); -extern void rs_unregister_softirq(uint32_t sirq_num); -extern void rs_do_softirq(); -extern void rs_clear_softirq_pending(uint32_t softirq_num); - -// for temporary -#define MAX_SOFTIRQ_NUM 64 -#define TIMER_SIRQ 0 // 时钟软中断号 -#define VIDEO_REFRESH_SIRQ 1 // 帧缓冲区刷新软中断 diff --git a/kernel/src/exception/softirq.rs b/kernel/src/exception/softirq.rs index 09c9cf48..7b9beb22 100644 --- a/kernel/src/exception/softirq.rs +++ b/kernel/src/exception/softirq.rs @@ -17,14 +17,14 @@ use crate::{ libs::rwlock::RwLock, mm::percpu::{PerCpu, PerCpuVar}, process::ProcessManager, - smp::core::smp_get_processor_id, + smp::{core::smp_get_processor_id, cpu::ProcessorId}, time::timer::clock, }; const MAX_SOFTIRQ_NUM: u64 = 64; const MAX_SOFTIRQ_RESTART: i32 = 20; -static mut __CPU_PENDING: Option> = None; +static mut __CPU_PENDING: Option> = None; static mut __SORTIRQ_VECTORS: *mut Softirq = null_mut(); #[no_mangle] @@ -57,9 +57,9 @@ pub fn softirq_vectors() -> &'static mut Softirq { } #[inline(always)] -fn cpu_pending(cpu_id: usize) -> &'static mut VecStatus { +fn cpu_pending(cpu_id: ProcessorId) -> &'static mut VecStatus { unsafe { - return &mut __CPU_PENDING.as_mut().unwrap()[cpu_id]; + return &mut __CPU_PENDING.as_mut().unwrap()[cpu_id.data() as usize]; } } @@ -165,7 +165,8 @@ impl Softirq { /// @brief 解注册软中断向量 /// - /// @param irq_num 中断向量号码 + /// @param irq_num 中断向量号码 + #[allow(dead_code)] pub fn unregister_softirq(&self, softirq_num: SoftirqNumber) { // kdebug!("unregister_softirq softirq_num = {:?}", softirq_num as u64); let mut table_guard = self.table.write_irqsave(); @@ -176,10 +177,11 @@ impl Softirq { // self.running.lock().set(VecStatus::from(softirq_num), false); // 将对应CPU的pending置0 compiler_fence(Ordering::SeqCst); - cpu_pending(smp_get_processor_id() as usize).set(VecStatus::from(softirq_num), false); + cpu_pending(smp_get_processor_id()).set(VecStatus::from(softirq_num), false); compiler_fence(Ordering::SeqCst); } + #[inline(never)] pub fn do_softirq(&self) { if self.cpu_running_count().get().load(Ordering::SeqCst) >= Self::MAX_RUNNING_PER_CPU { // 当前CPU的软中断嵌套层数已经达到最大值,不再执行 @@ -194,8 +196,8 @@ impl Softirq { let mut max_restart = MAX_SOFTIRQ_RESTART; loop { compiler_fence(Ordering::SeqCst); - let pending = cpu_pending(cpu_id as usize).bits; - cpu_pending(cpu_id as usize).bits = 0; + let pending = cpu_pending(cpu_id).bits; + cpu_pending(cpu_id).bits = 0; compiler_fence(Ordering::SeqCst); unsafe { CurrentIrqArch::interrupt_enable() }; @@ -229,7 +231,7 @@ impl Softirq { unsafe { CurrentIrqArch::interrupt_disable() }; max_restart -= 1; compiler_fence(Ordering::SeqCst); - if cpu_pending(cpu_id as usize).is_empty() { + if cpu_pending(cpu_id).is_empty() { compiler_fence(Ordering::SeqCst); if clock() < end && max_restart > 0 { continue; @@ -245,7 +247,7 @@ impl Softirq { pub fn raise_softirq(&self, softirq_num: SoftirqNumber) { let guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; - let processor_id = smp_get_processor_id() as usize; + let processor_id = smp_get_processor_id(); cpu_pending(processor_id).insert(VecStatus::from(softirq_num)); @@ -254,9 +256,11 @@ impl Softirq { drop(guard); // kdebug!("raise_softirq exited"); } + + #[allow(dead_code)] pub unsafe fn clear_softirq_pending(&self, softirq_num: SoftirqNumber) { compiler_fence(Ordering::SeqCst); - cpu_pending(smp_get_processor_id() as usize).remove(VecStatus::from(softirq_num)); + cpu_pending(smp_get_processor_id()).remove(VecStatus::from(softirq_num)); compiler_fence(Ordering::SeqCst); } } @@ -282,25 +286,6 @@ impl<'a> Drop for RunningCountGuard<'a> { } } -// ======= 以下为给C提供的接口 ======= -#[no_mangle] -pub extern "C" fn rs_raise_softirq(softirq_num: u32) { - softirq_vectors().raise_softirq(SoftirqNumber::from(softirq_num as u64)); -} - -#[no_mangle] -pub extern "C" fn rs_unregister_softirq(softirq_num: u32) { - softirq_vectors().unregister_softirq(SoftirqNumber::from(softirq_num as u64)); -} - -#[no_mangle] -pub extern "C" fn rs_do_softirq() { +pub fn do_softirq() { softirq_vectors().do_softirq(); } - -#[no_mangle] -pub extern "C" fn rs_clear_softirq_pending(softirq_num: u32) { - unsafe { - softirq_vectors().clear_softirq_pending(SoftirqNumber::from(softirq_num as u64)); - } -} diff --git a/kernel/src/exception/sysfs.rs b/kernel/src/exception/sysfs.rs index 31e60567..357b66d5 100644 --- a/kernel/src/exception/sysfs.rs +++ b/kernel/src/exception/sysfs.rs @@ -152,7 +152,8 @@ impl Attribute for AttrChipName { .arc_any() .downcast::() .map_err(|_| SystemError::EINVAL)?; - let chip = irq_desc.irq_data().chip(); + + let chip = irq_desc.irq_data().chip_info_read_irqsave().chip(); let name = chip.name(); let len = core::cmp::min(name.len() + 1, buf.len()); let name = format!("{}\n", name); @@ -301,9 +302,11 @@ impl Attribute for AttrActions { for action in actions { if len != 0 { - len += sysfs_emit_str(&mut buf[len..], &format!(",{}", action.name())).unwrap(); + len += sysfs_emit_str(&mut buf[len..], &format!(",{}", action.inner().name())) + .unwrap(); } else { - len += sysfs_emit_str(&mut buf[len..], &format!("{}", action.name())).unwrap(); + len += + sysfs_emit_str(&mut buf[len..], &format!("{}", action.inner().name())).unwrap(); } if len >= buf.len() { diff --git a/kernel/src/filesystem/procfs/mod.rs b/kernel/src/filesystem/procfs/mod.rs index 418f52e5..f5edfe26 100644 --- a/kernel/src/filesystem/procfs/mod.rs +++ b/kernel/src/filesystem/procfs/mod.rs @@ -157,7 +157,7 @@ impl ProcFSInode { let state = sched_info_guard.inner_lock_read_irqsave().state(); let cpu_id = sched_info_guard .on_cpu() - .map(|cpu| cpu as i32) + .map(|cpu| cpu.data() as i32) .unwrap_or(-1); let priority = sched_info_guard.priority(); diff --git a/kernel/src/filesystem/vfs/VFS.h b/kernel/src/filesystem/vfs/VFS.h deleted file mode 100644 index c66f2a43..00000000 --- a/kernel/src/filesystem/vfs/VFS.h +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @file VFS.h - * @author fslongjin (longjin@RinGoTek.cn) - * @brief 虚拟文件系统 - * @version 0.1 - * @date 2022-04-20 - * - * @copyright Copyright (c) 2022 - * - */ - -#pragma once - -struct vfs_file_operations_t -{ - long (*open)(void *not_used, void *not_used1); - long (*close)(void *not_used, void *not_used1); - long (*read)(void *not_used1, char *buf, int64_t count, long *position); - long (*write)(void *not_used1, char *buf, int64_t count, long *position); - long (*lseek)(void *not_used1, long offset, long origin); - long (*ioctl)(void *not_used, void *not_used1, uint64_t cmd, uint64_t arg); -}; - -/** - * @brief 初始化vfs - * - * @return int 错误码 - */ -extern int vfs_init(); diff --git a/kernel/src/include/bindings/wrapper.h b/kernel/src/include/bindings/wrapper.h index 8bc79ca2..1b03fdde 100644 --- a/kernel/src/include/bindings/wrapper.h +++ b/kernel/src/include/bindings/wrapper.h @@ -36,7 +36,5 @@ #include #include