完成中断管理模块重构 (#554)

- 支持中断共享
- 把现有驱动程序移植到新的irq模块
- 使用`ProcessorId`标识处理器id
- 尚未实现threaded_irq

性能上,edge irq flow handler里面,对于锁的使用,可能有点问题。为了获取/修改common data还有其他几个结构体的状态,进行了多次加锁和放锁,导致性能降低。这是接下来需要优化的点。
This commit is contained in:
LoGin 2024-03-03 16:31:08 +08:00 committed by GitHub
parent 44d051e586
commit e28411791f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
108 changed files with 4504 additions and 2203 deletions

View File

@ -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",

View File

@ -18,7 +18,6 @@ impl CFilesArch for X86_64CFilesArch {
}
fn setup_files(&self, _c: &mut Build, files: &mut Vec<PathBuf>) {
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"),

View File

@ -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);
```

View File

@ -2,6 +2,7 @@ use alloc::vec::Vec;
use crate::{bitmap_core::BitMapCore, traits::BitMapOps};
#[derive(Clone)]
pub struct AllocBitmap {
elements: usize,
data: Vec<usize>,

View File

@ -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:

View File

@ -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")
}

View File

@ -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!(

View File

@ -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();
}

View File

@ -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

View File

@ -1,205 +0,0 @@
#include "apic.h"
#include "apic_timer.h"
#include <common/cpu.h>
#include <common/glib.h>
#include <common/kprint.h>
#include <common/printk.h>
#include <driver/acpi/acpi.h>
#include <exception/softirq.h>
#include <process/process.h>
#include <sched/sched.h>
#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

View File

@ -1,284 +0,0 @@
#pragma once
#include <common/asm.h>
#include <process/ptrace.h>
#include <exception/irq.h>
#include <mm/mm.h>
#include <arch/arch.h>
#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

View File

@ -1,96 +0,0 @@
#include "apic_timer.h"
#include <common/kprint.h>
#include <exception/irq.h>
#include <process/process.h>
#include <sched/sched.h>
// 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());
}

View File

@ -1,14 +0,0 @@
#pragma once
#include <common/unistd.h>
#include "apic.h"
#define APIC_TIMER_IRQ_NUM 151
/**
* @brief local APIC定时器
*
*/
void apic_timer_init();
void apic_timer_ap_core_init();

View File

@ -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<LocalApicTimer>; 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<LocalApicTimer>; 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<Arc<dyn IrqHandlerData>>,
) -> Result<IrqReturn, SystemError> {
// empty (只是为了让编译通过不会被调用到。真正的处理函数在LocalApicTimerIrqFlowHandler中)
Ok(IrqReturn::NotHandled)
}
}
#[derive(Debug)]
struct LocalApicTimerIrqFlowHandler;
impl IrqFlowHandler for LocalApicTimerIrqFlowHandler {
fn handle(&self, _irq_desc: &Arc<IrqDesc>, _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<crate::exception::irqdata::IrqData> = 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<IrqReturn, SystemError> {
sched_update_jiffies();
return Ok(());
return Ok(IrqReturn::Handled);
}
}

View File

@ -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());
}

View File

@ -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,
}

View File

@ -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<SpinLock<IoApic>> = None;
static mut IOAPIC_IR_CHIP: Option<Arc<IoApicChip>> = None;
#[allow(non_snake_case)]
fn IOAPIC() -> &'static SpinLock<IoApic> {
unsafe { __IOAPIC.as_ref().unwrap() }
}
#[inline(always)]
pub(super) fn ioapic_ir_chip() -> Arc<dyn IrqChip> {
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<InnerIoApicChipData>,
}
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<InnerIoApicChipData> {
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<IrqDesc>, 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<IrqData>) -> Result<(), SystemError> {
self.irq_unmask(irq)
}
fn irq_mask(&self, irq: &Arc<IrqData>) -> Result<(), SystemError> {
let binding = irq
.chip_info_read_irqsave()
.chip_data()
.ok_or(SystemError::EINVAL)?;
let chip_data = binding
.as_any_ref()
.downcast_ref::<IoApicChipData>()
.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<IrqData>,
flow_type: IrqLineStatus,
) -> Result<IrqChipSetMaskResult, SystemError> {
let binding = irq
.chip_info_read_irqsave()
.chip_data()
.ok_or(SystemError::EINVAL)?;
let chip_data = binding
.as_any_ref()
.downcast_ref::<IoApicChipData>()
.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<IrqData>,
cpu: &CpuMask,
_force: bool,
) -> Result<IrqChipSetMaskResult, SystemError> {
// 使用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::<IoApicChipData>()
.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<IrqData>) -> 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<IrqData>) {
self.irq_mask(irq).ok();
self.irq_eoi(irq);
}
fn irq_eoi(&self, irq: &Arc<IrqData>) {
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<IrqData>) -> Result<(), SystemError> {
irq_manager().irq_chip_retrigger_hierarchy(irq_data)
}
fn irqchip_state(&self, irq: &Arc<IrqData>, which: IrqChipState) -> Result<bool, SystemError> {
let binding = irq
.chip_info_read_irqsave()
.chip_data()
.ok_or(SystemError::EINVAL)?;
let chip_data = binding
.as_any_ref()
.downcast_ref::<IoApicChipData>()
.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<IrqData>) {
let binding = irq
.chip_info_read_irqsave()
.chip_data()
.ok_or(SystemError::EINVAL)
.unwrap();
let chip_data = binding
.as_any_ref()
.downcast_ref::<IoApicChipData>()
.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<IrqData>) {
// 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
}
}

View File

@ -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<Arc<LocalApicChip>> = None;
pub fn local_apic_chip() -> &'static Arc<LocalApicChip> {
unsafe { LOCAL_APIC_CHIP.as_ref().unwrap() }
}
#[derive(Debug)]
pub struct LocalApicChip {
inner: SpinLock<InnerIrqChip>,
}
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<IrqData>) {}
fn irq_ack(&self, _irq: &Arc<IrqData>) {
CurrentApic.send_eoi();
}
fn can_set_affinity(&self) -> bool {
false
}
fn can_mask_ack(&self) -> bool {
false
}
fn irq_enable(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
// 这里临时处理,后续需要修改
return Ok(());
}
fn irq_unmask(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
Ok(())
}
fn irq_compose_msi_msg(&self, irq: &Arc<IrqData>, msg: &mut MsiMsg) {
let chip_data = irq.chip_info_read_irqsave().chip_data().unwrap();
let apicd = chip_data.ref_any().downcast_ref::<ApicChipData>().unwrap();
let cfg = &apicd.inner().hw_irq_cfg;
irq_msi_compose_msg(cfg, msg, false);
}
fn retrigger(&self, irq: &Arc<IrqData>) -> Result<(), SystemError> {
let chip_data = irq
.chip_info_read_irqsave()
.chip_data()
.ok_or(SystemError::EINVAL)?;
let apicd = chip_data
.ref_any()
.downcast_ref::<ApicChipData>()
.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<InnerApicChipData>,
}
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<InnerApicChipData> {
self.inner.lock_irqsave()
}
}
#[allow(dead_code)]
#[derive(Debug)]
struct InnerApicChipData {
hw_irq_cfg: HardwareIrqConfig,
irq: IrqNumber,
vector: HardwareIrqNumber,
prev_vector: Option<HardwareIrqNumber>,
cpu: ProcessorId,
prev_cpu: Option<ProcessorId>,
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来
* 320xFFExxxxx寻址的APIC
* 85-11使ID字段
* 15APIC 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<Arc<IrqDomain>> = None;
#[inline(always)]
#[allow(dead_code)]
pub fn x86_vector_domain() -> &'static Arc<IrqDomain> {
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<IrqDomain>,
_device_node: &Arc<DeviceNode>,
_bus_token: IrqDomainBusToken,
) -> bool {
todo!()
}
fn map(
&self,
_irq_domain: &Arc<IrqDomain>,
_hwirq: HardwareIrqNumber,
_virq: IrqNumber,
) -> Result<(), SystemError> {
Err(SystemError::ENOSYS)
}
fn unmap(&self, _irq_domain: &Arc<IrqDomain>, _virq: IrqNumber) {
todo!()
}
}

View File

@ -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));
}
}

View File

@ -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) 寄存器

View File

@ -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<Option<XApic>>; PerCpu::MAX_CPU_NUM] =
[const { RefCell::new(None) }; PerCpu::MAX_CPU_NUM];
static mut XAPIC_INSTANCES: [RefCell<Option<XApic>>; 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<Option<XApic>> {
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寄存器的值

View File

@ -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);
}

View File

@ -1,26 +0,0 @@
#include <common/glib.h>
#include <common/kprint.h>
#include <arch/x86_64/driver/apic/apic.h>
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");
}

View File

@ -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<Hpet> = 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<Self, SystemError> {
let paddr = PhysAddr::new(hpet_info.base_address);
let map_size = size_of::<HpetRegisters>();
@ -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<Arc<dyn IrqHandlerData>>,
) -> Result<IrqReturn, SystemError> {
hpet_instance().handle_irq(0);
return Ok(IrqReturn::Handled);
}
}

View File

@ -1,5 +1,4 @@
pub mod apic;
mod c_adapter;
pub mod hpet;
pub mod tsc;
pub mod video;

View File

@ -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 <common/kprint.h>
#include <arch/x86_64/driver/apic/apic.h>
/**
* @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);

View File

@ -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());
}

View File

@ -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));

View File

@ -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();
}
}

View File

@ -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<IpiKind> for ArchIpiKind {
@ -22,6 +35,17 @@ impl From<IpiKind> for ArchIpiKind {
match kind {
IpiKind::KickCpu => ArchIpiKind::KickCpu,
IpiKind::FlushTLB => ArchIpiKind::FlushTLB,
IpiKind::SpecVector(vec) => ArchIpiKind::SpecVector(vec),
}
}
}
impl Into<u8> 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<IpiTarget> 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<x86::apic::DestinationShorthand> 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<IrqData> = 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<IrqDesc>, _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();
}
}

View File

@ -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()
}
}
/// 中断栈帧结构体

View File

@ -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,
}

View File

@ -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");

View File

@ -1,15 +0,0 @@
#include "x86_64_ipi.h"
#include <arch/x86_64/driver/apic/apic.h>
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;
}

View File

@ -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);
}

View File

@ -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(

View File

@ -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);
}
}

View File

@ -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<usize>; PerCpu::MAX_CPU_NUM]>,
ia64_cpu_to_sapicid: RwLock<[Option<usize>; 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

View File

@ -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 "$@"

View File

@ -50,7 +50,7 @@ pub fn driver_manager() -> &'static DriverManager {
/// 否则在运行时会报错
pub trait Driver: Sync + Send + Debug + KObject {
fn coredump(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
Err(SystemError::EOPNOTSUPP_OR_ENOTSUP)
Err(SystemError::ENOSYS)
}
/// @brief: 获取驱动标识符

View File

@ -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<String>,
@ -883,7 +884,7 @@ pub struct DeviceId {
impl DeviceId {
#[allow(dead_code)]
pub fn new(data: Option<&'static str>, allocated: Option<String>) -> Option<Self> {
pub fn new(data: Option<&'static str>, allocated: Option<String>) -> Option<Arc<Self>> {
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 {}

View File

@ -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,
}

View File

@ -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<alloc::vec::Vec<alloc::string::String>, SystemError> {
fn list(&self) -> Result<Vec<alloc::string::String>, SystemError> {
todo!()
}

View File

@ -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() {
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<Arc<dyn IrqHandlerData>>,
) -> Result<IrqReturn, SystemError> {
if let Some(psmouse_device) = ps2_mouse_device() {
ps2_mouse_driver()
return Ok(ps2_mouse_driver()
.interrupt(&(psmouse_device as Arc<dyn SerioDevice>), 0, 0)
.ok();
.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(());
}

View File

@ -1,10 +0,0 @@
SRC = $(wildcard *.c)
OBJ = $(SRC:.c=.o)
CFLAGS += -I .
.PHONY: all
all: $(OBJ)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@

View File

@ -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(());
}

View File

@ -1,209 +0,0 @@
#include "ps2_keyboard.h"
#include <arch/x86_64/driver/apic/apic.h>
#include <mm/mm.h>
#include <mm/slab.h>
#include <common/printk.h>
#include <filesystem/vfs/VFS.h>
#include <common/spinlock.h>
#include <common/kfifo.h>
// 键盘输入缓冲区
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);
}

View File

@ -1,40 +0,0 @@
#pragma once
#include <common/glib.h>
#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();

View File

@ -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<PS2KeyBoardInode>, AtomicI32); // self.1 用来记录有多少个文件打开了这个inode
pub struct LockedPS2KeyBoardInode(RwLock<PS2KeyBoardInode>);
lazy_static! {
static ref PS2_KEYBOARD_FSM: SpinLock<TypeOneFSM> = SpinLock::new(TypeOneFSM::new());
@ -33,17 +65,14 @@ pub struct PS2KeyBoardInode {
fs: Weak<DevFS>,
/// INode 元数据
metadata: Metadata,
/// 键盘操作函数
f_ops: vfs_file_operations_t,
}
impl LockedPS2KeyBoardInode {
pub fn new(f_ops: &vfs_file_operations_t) -> Arc<Self> {
pub fn new() -> Arc<Self> {
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<usize, SystemError> {
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<usize, SystemError> {
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) {
#[derive(Debug)]
struct Ps2KeyboardIrqHandler;
impl IrqHandler for Ps2KeyboardIrqHandler {
fn handle(
&self,
_irq: IrqNumber,
_static_data: Option<&dyn IrqHandlerData>,
_dev_id: Option<Arc<dyn IrqHandlerData>>,
) -> Result<IrqReturn, SystemError> {
// 先检查状态寄存器,看看是否有数据
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(())
}

View File

@ -1,10 +0,0 @@
SRC = $(wildcard *.c)
OBJ = $(SRC:.c=.o)
CFLAGS += -I .
.PHONY: all
all: $(OBJ)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@

View File

@ -1,58 +0,0 @@
#include "ps2_mouse.h"
#include <arch/x86_64/driver/apic/apic.h>
#include <mm/mm.h>
#include <mm/slab.h>
#include <common/printk.h>
#include <common/kprint.h>
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");
}

View File

@ -1,38 +0,0 @@
#pragma once
#include <common/glib.h>
#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();

View File

@ -1,6 +1,8 @@
// 参考手册: PCIe* GbE Controllers Open Source Software Developers Manual
// Refernce: PCIe* GbE Controllers Open Source Software Developers 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<Self, E1000EPciError> {
pub fn new(
device: &mut PciDeviceStructureGeneralDevice,
device_id: Arc<DeviceId>,
) -> Result<Self, E1000EPciError> {
// 从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<u64, E1000EPciError> {
"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);
}
}

View File

@ -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<Arc<dyn IrqHandlerData>>,
) -> Result<IrqReturn, SystemError> {
poll_ifaces_try_lock_onetime().ok();
Ok(IrqReturn::Handled)
}
}

View File

@ -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 {

View File

@ -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<T: Transport> Clone for VirtioNICDriver<T> {
}
}
/// @brief 网卡驱动的包裹器,这是为了获取网卡驱动的可变引用而设计的。
/// 网卡驱动的包裹器,这是为了获取网卡驱动的可变引用而设计的。
///
/// 由于smoltcp的设计导致需要在poll的时候获取网卡驱动的可变引用
/// 同时需要在token的consume里面获取可变引用。为了避免双重加锁所以需要这个包裹器。
struct VirtioNICDriverWrapper<T: Transport>(UnsafeCell<VirtioNICDriver<T>>);
@ -76,6 +78,7 @@ pub struct VirtioInterface<T: Transport> {
iface_id: usize,
iface: SpinLock<smoltcp::iface::Interface>,
name: String,
dev_id: Arc<DeviceId>,
}
impl<T: Transport> Debug for VirtioInterface<T> {
@ -90,7 +93,7 @@ impl<T: Transport> Debug for VirtioInterface<T> {
}
impl<T: Transport> VirtioInterface<T> {
pub fn new(mut driver: VirtioNICDriver<T>) -> Arc<Self> {
pub fn new(mut driver: VirtioNICDriver<T>, dev_id: Arc<DeviceId>) -> Arc<Self> {
let iface_id = generate_iface_id();
let mut iface_config = smoltcp::iface::Config::new();
@ -109,12 +112,31 @@ impl<T: Transport> VirtioInterface<T> {
iface_id,
iface: SpinLock::new(iface),
name: format!("eth{}", iface_id),
dev_id,
});
return result;
}
}
impl<T: Transport + 'static> VirtIODevice for VirtioInterface<T> {
fn handle_irq(&self, _irq: IrqNumber) -> Result<IrqReturn, SystemError> {
poll_ifaces_try_lock_onetime().ok();
return Ok(IrqReturn::Handled);
}
fn dev_id(&self) -> &Arc<DeviceId> {
return &self.dev_id;
}
}
impl<T: Transport> Drop for VirtioInterface<T> {
fn drop(&mut self) {
// 从全局的网卡接口信息表中删除这个网卡的接口信息
NET_DRIVERS.write_irqsave().remove(&self.iface_id);
}
}
impl<T: 'static + Transport> VirtioNICDriver<T> {
pub fn new(driver_net: VirtIONet<HalImpl, T, 2>) -> Self {
let mut iface_config = smoltcp::iface::Config::new();
@ -223,7 +245,7 @@ impl<T: Transport> phy::RxToken for VirtioNetToken<T> {
}
/// @brief virtio-net 驱动的初始化与测试
pub fn virtio_net<T: Transport + 'static>(transport: T) {
pub fn virtio_net<T: Transport + 'static>(transport: T, dev_id: Arc<DeviceId>) {
let driver_net: VirtIONet<HalImpl, T, 2> =
match VirtIONet::<HalImpl, T, 2>::new(transport, 4096) {
Ok(net) => net,
@ -234,12 +256,16 @@ pub fn virtio_net<T: Transport + 'static>(transport: T) {
};
let mac = smoltcp::wire::EthernetAddress::from_bytes(&driver_net.mac_address());
let driver: VirtioNICDriver<T> = 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,

View File

@ -1,11 +0,0 @@
SRC = $(wildcard *.c)
OBJ = $(SRC:.c=.o)
CFLAGS += -I .
.PHONY: all
all: $(OBJ)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@

View File

@ -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<u16>>;
fn irq_vector_mut(&mut self) -> Option<&mut Vec<IrqNumber>>;
}
/// Pci_Device_Structure_Header PCI设备结构体共有的头部
@ -404,7 +405,7 @@ pub struct PciDeviceStructureGeneralDevice {
// 中断结构体包括legacy,msi,msix三种情况
pub irq_type: IrqType,
// 使用的中断号的vec集合
pub irq_vector: Vec<u16>,
pub irq_vector: Vec<IrqNumber>,
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<u16>> {
fn irq_vector_mut(&mut self) -> Option<&mut Vec<IrqNumber>> {
Some(&mut self.irq_vector)
}
}
@ -476,7 +477,7 @@ pub struct PciDeviceStructurePciToPciBridge {
// 中断结构体包括legacy,msi,msix三种情况
pub irq_type: IrqType,
// 使用的中断号的vec集合
pub irq_vector: Vec<u16>,
pub irq_vector: Vec<IrqNumber>,
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<u16>> {
fn irq_vector_mut(&mut self) -> Option<&mut Vec<IrqNumber>> {
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<u16>> {
fn irq_vector_mut(&mut self) -> Option<&mut Vec<IrqNumber>> {
None
}
}

View File

@ -1,95 +0,0 @@
#include "pci_irq.h"
#include "exception/irq.h"
#include <common/errno.h>
#include <common/kprint.h>
#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;
}

View File

@ -1,5 +0,0 @@
#pragma once
#include <common/glib.h>
#include <process/ptrace.h>
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);

View File

@ -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,
@ -79,28 +82,34 @@ pub struct PciIrqMsg {
#[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<unsafe extern "C" fn(irq_num: ul)>, // 中断的ack可为None,若为None则中断处理中会正常通知中断结束不为None则调用传入的函数进行回复
irq_name: String, //中断名字
irq_hander: &'static dyn IrqHandler, // 中断处理函数
/// 全局设备标志符
dev_id: Arc<DeviceId>,
}
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<unsafe extern "C" fn(irq_num: ul)>,
irq_name: String,
irq_hander: &'static dyn IrqHandler,
dev_id: Arc<DeviceId>,
) -> 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<DeviceId> {
&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

View File

@ -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<VirtIOIrqManager> = None;
#[inline(always)]
pub fn virtio_irq_manager() -> &'static VirtIOIrqManager {
unsafe { VIRTIO_IRQ_MANAGER.as_ref().unwrap() }
}
pub struct VirtIOIrqManager {
map: RwLock<HashMap<Arc<DeviceId>, Arc<dyn VirtIODevice>>>,
}
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<dyn VirtIODevice>) -> 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<DeviceId>) {
let mut map = self.map.write_irqsave();
map.remove(dev_id);
}
/// 查找并返回指定设备ID的设备。
///
/// # 参数
/// - `dev_id` - 我们要查找的设备的设备ID。
///
/// # 返回
/// - 如果找到了设备,返回一个包含设备的`Option<Arc<dyn VirtIODevice>>`。
/// - 如果没有找到设备,返回`None`。
pub fn lookup_device(&self, dev_id: &Arc<DeviceId>) -> Option<Arc<dyn VirtIODevice>> {
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(());
}

View File

@ -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<IrqReturn, SystemError>;
fn dev_id(&self) -> &Arc<DeviceId>;
}

View File

@ -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<Volatile<u8>>,
/// The VirtIO device-specific configuration within some BAR.
config_space: Option<NonNull<[u32]>>,
}
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<DeviceId>,
}
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<H: Hal>(
device: &mut PciDeviceStructureGeneralDevice,
dev_id: Arc<DeviceId>,
) -> Result<Self, VirtioPciError> {
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<T>(
fn nonnull_slice_from_raw_parts<T>(data: NonNull<T>, 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<Arc<dyn IrqHandlerData>>,
) -> Result<IrqReturn, SystemError> {
let dev_id = dev_id.ok_or(SystemError::EINVAL)?;
let dev_id = dev_id
.arc_any()
.downcast::<DeviceId>()
.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);
}
}
}

View File

@ -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::<HalImpl>(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::<HalImpl>(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<DeviceId>) {
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);
}

View File

@ -1,8 +0,0 @@
CFLAGS += -I .
all: irq.o
irq.o: irq.c
$(CC) $(CFLAGS) -c irq.c -o irq.o

View File

@ -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<IrqData>) -> Result<(), SystemError> {
Ok(())
}
fn can_set_affinity(&self) -> bool {
false
}
fn can_set_flow_type(&self) -> bool {
false
}
fn irq_disable(&self, _irq: &Arc<IrqData>) {}
fn irq_ack(&self, irq: &Arc<IrqData>) {
@ -78,17 +91,26 @@ impl IrqChip for DummyIrqChip {
"dummy"
}
fn can_mask_ack(&self) -> bool {
false
}
fn irq_enable(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
Ok(())
}
fn can_set_flow_type(&self) -> bool {
false
}
fn can_set_affinity(&self) -> bool {
false
}
fn irq_disable(&self, _irq: &Arc<IrqData>) {}
fn irq_ack(&self, _irq: &Arc<IrqData>) {}
fn irq_mask(&self, _irq: &Arc<IrqData>) {}
fn irq_unmask(&self, _irq: &Arc<IrqData>) {}
fn irq_startup(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
Ok(())
}

View File

@ -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<IrqDesc>) {
fn handle(&self, irq_desc: &Arc<IrqDesc>, _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<IrqDesc>, _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<IrqDesc>, _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<IrqData>) {
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<IrqDesc>,
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<IrqDesc>) -> 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<dyn IrqHandlerData>);
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()
);
}

View File

@ -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");
// 初始化架构相关的中断

View File

@ -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<Arc<dyn IrqHandlerData>>,
) -> Result<IrqReturn, SystemError> {
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<Arc<dyn IrqHandlerData>>,
) -> Result<IrqReturn, SystemError> {
unsafe { MMArch::invalidate_all() };
Ok(IrqReturn::Handled)
}
}

View File

@ -1,84 +0,0 @@
#include "irq.h"
#include <common/errno.h>
#include <common/asm.h>
#include <common/printk.h>
#include <common/string.h>
#include <mm/slab.h>
#include <arch/arch.h>
#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")

View File

@ -1,175 +0,0 @@
/**
* @file irq.h
* @author longjin
* @brief
* @version 0.1
* @date 2022-01-28
*
* @copyright Copyright (c) 2022
*
*/
#pragma once
#include <common/glib.h>
#include <process/ptrace.h>
#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

View File

@ -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<IrqData>);
/// mask an interrupt source
fn irq_mask(&self, _irq: &Arc<IrqData>) {}
///
/// 用于屏蔽中断
///
/// 如果返回ENOSYS则表明irq_mask()不支持.
///
/// 如果返回错误,那么中断的屏蔽状态将不会改变。
fn irq_mask(&self, _irq: &Arc<IrqData>) -> 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<IrqData>) {}
/// unmask an interrupt source
fn irq_unmask(&self, _irq: &Arc<IrqData>) {}
///
/// 用于取消屏蔽中断
///
/// 如果返回ENOSYS则表明irq_unmask()不支持.
fn irq_unmask(&self, _irq: &Arc<IrqData>) -> Result<(), SystemError> {
Err(SystemError::ENOSYS)
}
/// end of interrupt
fn irq_eoi(&self, _irq: &Arc<IrqData>) {}
// todo: set affinity
/// 指示当前芯片是否可以设置中断亲和性。
fn can_set_affinity(&self) -> bool;
/// 在SMP机器上设置CPU亲和性。
///
/// 如果force参数为真它告诉驱动程序无条件地应用亲和性设置。
/// 不需要对提供的亲和性掩码进行完整性检查。这用于CPU热插拔其中目标CPU尚未在cpu_online_mask中设置。
fn irq_set_affinity(
&self,
_irq: &Arc<IrqData>,
_cpu: &CpuMask,
_force: bool,
) -> Result<IrqChipSetMaskResult, SystemError> {
Err(SystemError::ENOSYS)
}
/// retrigger an IRQ to the CPU
fn retrigger(&self, _irq: &Arc<IrqData>) {}
fn retrigger(&self, _irq: &Arc<IrqData>) -> 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<IrqData>,
_flow_type: IrqLineStatus,
) -> Result<(), SystemError> {
) -> Result<IrqChipSetMaskResult, SystemError> {
Err(SystemError::ENOSYS)
}
@ -108,6 +152,8 @@ pub trait IrqChip: Sync + Send + Any + Debug {
fn irq_release_resources(&self, _irq: &Arc<IrqData>) {}
/// optional to compose message content for MSI
///
/// 组装MSI消息并返回到msg中
fn irq_compose_msi_msg(&self, _irq: &Arc<IrqData>, _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<IrqData>) {
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<IrqData>) -> Result<(), SystemError> {
let mut data: Option<Arc<IrqData>> = 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(());
}
}

View File

@ -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<InnerIrqData>,
chip_info: RwLock<InnerIrqChipInfo>,
}
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<dyn IrqChip> {
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<IrqCommonData> {
self.inner.lock_irqsave().common_data.clone()
}
pub fn domain(&self) -> Option<Arc<IrqDomain>> {
self.inner.lock_irqsave().domain.clone()
}
pub fn inner(&self) -> SpinLockGuard<InnerIrqData> {
self.inner.lock_irqsave()
}
pub fn chip_info_read(&self) -> RwLockReadGuard<InnerIrqChipInfo> {
self.chip_info.read()
}
pub fn chip_info_read_irqsave(&self) -> RwLockReadGuard<InnerIrqChipInfo> {
self.chip_info.read_irqsave()
}
pub fn chip_info_write_irqsave(&self) -> RwLockWriteGuard<InnerIrqChipInfo> {
self.chip_info.write_irqsave()
}
pub fn parent_data(&self) -> Option<Weak<IrqData>> {
self.inner.lock_irqsave().parent_data.clone()
}
}
#[allow(dead_code)]
#[derive(Debug)]
struct InnerIrqData {
pub struct InnerIrqData {
/// 硬件中断号, 用于表示在某个IrqDomain中的中断号
hwirq: HardwareIrqNumber,
/// 涉及的所有irqchip之间共享的数据
common_data: Arc<IrqCommonData>,
/// 绑定到的中断芯片
chip: Arc<dyn IrqChip>,
/// 中断芯片的私有数据与当前irq相关
chip_data: Option<Arc<dyn IrqChipData>>,
/// 中断域
domain: Option<Arc<IrqDomain>>,
/// 中断的父中断(如果具有中断域继承的话)
parent_data: Option<Weak<IrqData>>,
}
impl InnerIrqData {
pub fn set_hwirq(&mut self, hwirq: HardwareIrqNumber) {
self.hwirq = hwirq;
}
#[allow(dead_code)]
pub fn domain(&self) -> Option<Arc<IrqDomain>> {
self.domain.clone()
}
pub fn set_domain(&mut self, domain: Option<Arc<IrqDomain>>) {
self.domain = domain;
}
}
#[derive(Debug)]
pub struct InnerIrqChipInfo {
/// 绑定到的中断芯片
chip: Option<Arc<dyn IrqChip>>,
/// 中断芯片的私有数据与当前irq相关
chip_data: Option<Arc<dyn IrqChipData>>,
}
impl InnerIrqChipInfo {
pub fn set_chip(&mut self, chip: Option<Arc<dyn IrqChip>>) {
self.chip = chip;
}
pub fn set_chip_data(&mut self, chip_data: Option<Arc<dyn IrqChipData>>) {
self.chip_data = chip_data;
}
pub fn chip(&self) -> Arc<dyn IrqChip> {
self.chip.clone().unwrap()
}
pub fn chip_data(&self) -> Option<Arc<dyn IrqChipData>> {
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<Arc<dyn IrqHandlerData>>,
msi_desc: Option<Arc<MsiDesc>>,
// 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<bool> {
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)
}
}

View File

@ -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<IrqDesc>);
pub trait IrqFlowHandler: Debug + Send + Sync + Any {
fn handle(&self, irq_desc: &Arc<IrqDesc>, trap_frame: &mut TrapFrame);
}
/// 中断处理程序
pub trait IrqHandler: Debug + Send + Sync + Any {
fn handle(
&self,
irq: IrqNumber,
static_data: Option<&dyn IrqHandlerData>,
dynamic_data: Option<Arc<dyn IrqHandlerData>>,
) -> Result<IrqReturn, SystemError>;
}
/// 中断处理函数返回值
///
/// 用于指示中断处理函数是否处理了中断
#[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<InnerIrqDesc>,
handler: SpinLock<Option<&'static dyn IrqFlowHandler>>,
handler: RwLock<Option<&'static dyn IrqFlowHandler>>,
/// 一个用于串行化 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<InnerIrqDesc> {
/// 增加当前活跃的中断线程数量, 返回增加前的值
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<InnerIrqDesc> {
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<String> {
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<IrqCommonData>,
irq_data: Arc<IrqData>,
@ -149,10 +317,134 @@ struct InnerIrqDesc {
/// nested wake enables
wake_depth: u32,
desc_internal_state: IrqDescState,
/// 中断线的状态
line_status: IrqLineStatus,
kern_inode: Option<Arc<KernFSInode>>,
kset: Option<Arc<KSet>>,
parent_kobj: Option<Weak<dyn KObject>>,
// 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<Arc<IrqAction>> {
&self.actions
}
pub fn add_action(&mut self, action: Arc<IrqAction>) {
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<IrqData> {
&self.irq_data
}
pub fn common_data(&self) -> &Arc<IrqCommonData> {
&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<InnerIrqAction>,
/// 用于等待线程被创建的完成量
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<Self> {
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<InnerIrqAction> {
self.inner.lock_irqsave()
}
fn inner(&self) -> SpinLockGuard<InnerIrqAction> {
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<DeviceId>,
dev_id: Option<Arc<DeviceId>>,
/// 中断处理程序
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<Arc<ProcessControlBlock>>,
/// 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<Arc<DeviceId>> {
&self.dev_id
}
pub fn dev_id_mut(&mut self) -> &mut Option<Arc<DeviceId>> {
&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<Arc<ProcessControlBlock>> {
self.thread.clone()
}
pub fn set_thread(&mut self, thread: Option<Arc<ProcessControlBlock>>) {
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<Arc<IrqAction>> {
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<IrqDescManager> = 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<IrqNumber, Arc<IrqDesc>>,
}
@ -367,7 +794,6 @@ impl IrqDescManager {
}
/// 查找中断描述符
#[allow(dead_code)]
pub fn lookup(&self, irq: IrqNumber) -> Option<Arc<IrqDesc>> {
self.irq_descs.get(&irq).map(|desc| desc.clone())
}

View File

@ -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<Arc<IrqDomainManager>> = None;
/// 获取中断域管理器的引用
#[inline(always)]
pub fn irq_domain_manager() -> &'static Arc<IrqDomainManager> {
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<Vec<Arc<IrqDomain>>>,
inner: RwLock<InnerIrqDomainManager>,
}
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<Arc<IrqDomain>> {
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<IrqDomain>) {
self.domains.lock_irqsave().push(domain);
}
#[allow(dead_code)]
pub fn remove_domain(&self, domain: &Arc<IrqDomain>) {
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<Arc<IrqDomain>> {
self.inner.read().default_domain.clone()
}
/// 设置默认的中断域
///
/// 在创建IRQ映射的时候如果没有指定中断域就会使用默认的中断域
pub fn set_default_domain(&self, domain: Arc<IrqDomain>) {
self.inner.write_irqsave().default_domain = Some(domain);
}
/// 将指定范围的硬件中断号与软件中断号一一对应的关联起来
///
/// ## 参数
///
/// - `domain` - 中断域
/// - `first_irq` - 起始软件中断号
/// - `first_hwirq` - 起始硬件中断号
/// - `count` - 数量
pub fn domain_associate_many(
&self,
domain: &Arc<IrqDomain>,
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<IrqDomain>,
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<IrqDomain>,
hwirq: HardwareIrqNumber,
irq_data: Arc<IrqData>,
) {
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<IrqData>, 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<Arc<IrqData>>,
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<Arc<IrqData>>) {
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<Arc<IrqDomain>>,
}
/// 中断域
///
/// 用于把硬件中断号翻译为软件中断号的映射的对象
@ -28,7 +288,7 @@ use super::{
pub struct IrqDomain {
/// 中断域的名字 (二选一)
name: Option<&'static str>,
allocated_name: Option<String>,
allocated_name: SpinLock<Option<String>>,
/// 中断域的操作
ops: &'static dyn IrqDomainOps,
inner: SpinLock<InnerIrqDomain>,
@ -63,6 +323,8 @@ impl IrqDomain {
ops: &'static dyn IrqDomainOps,
flags: IrqDomainFlags,
bus_token: IrqDomainBusToken,
irq_max: IrqNumber,
hwirq_max: HardwareIrqNumber,
) -> Option<Arc<Self>> {
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<String> {
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<HardwareIrqNumber, IrqNumber>,
map: HashMap<HardwareIrqNumber, Arc<IrqData>>,
hwirq_max: HardwareIrqNumber,
irq_max: IrqNumber,
}
impl IrqDomainRevMap {
fn insert(&mut self, hwirq: HardwareIrqNumber, irq_data: Arc<IrqData>) {
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<Arc<IrqData>> {
self.map.get(&hwirq).cloned()
}
}
bitflags! {
@ -156,15 +465,30 @@ pub trait IrqDomainOps: Debug + Send + Sync {
/// 创建或更新一个虚拟中断号与一个硬件中断号之间的映射。
/// 对于给定的映射,这只会被调用一次。
///
/// 如果没有实现这个方法,那么就会返回`ENOSYS`
fn map(
&self,
irq_domain: &Arc<IrqDomain>,
hwirq: HardwareIrqNumber,
virq: IrqNumber,
) -> Result<(), SystemError>;
_irq_domain: &Arc<IrqDomain>,
_hwirq: HardwareIrqNumber,
_virq: IrqNumber,
) -> Result<(), SystemError> {
Err(SystemError::ENOSYS)
}
/// 删除一个虚拟中断号与一个硬件中断号之间的映射。
fn unmap(&self, irq_domain: &Arc<IrqDomain>, virq: IrqNumber);
fn activate(
&self,
_domain: &Arc<IrqDomain>,
_irq_data: &Arc<IrqData>,
_reserve: bool,
) -> Result<(), SystemError> {
Err(SystemError::ENOSYS)
}
fn deactivate(&self, _domain: &Arc<IrqDomain>, _irq_data: &Arc<IrqData>) {}
}
#[allow(dead_code)]

File diff suppressed because it is too large Load Diff

View File

@ -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<u32> for HardwareIrqNumber {
type Output = HardwareIrqNumber;
fn add(self, rhs: u32) -> HardwareIrqNumber {
HardwareIrqNumber::new(self.0 + rhs)
}
}
impl Add<u32> for IrqNumber {
type Output = IrqNumber;
fn add(self, rhs: u32) -> IrqNumber {
IrqNumber::new(self.0 + rhs)
}
}

View File

@ -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)]

View File

@ -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 bitsuspend/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());
}
}

View File

@ -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 <common/glib.h>
// ==================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 // 帧缓冲区刷新软中断

View File

@ -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<Box<[VecStatus; PerCpu::MAX_CPU_NUM]>> = None;
static mut __CPU_PENDING: Option<Box<[VecStatus; PerCpu::MAX_CPU_NUM as usize]>> = 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];
}
}
@ -166,6 +166,7 @@ impl Softirq {
/// @brief 解注册软中断向量
///
/// @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));
}
}

View File

@ -152,7 +152,8 @@ impl Attribute for AttrChipName {
.arc_any()
.downcast::<IrqDesc>()
.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() {

View File

@ -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();

View File

@ -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();

View File

@ -36,7 +36,5 @@
#include <smp/smp.h>
#include <time/clocksource.h>
#include <time/sleep.h>
#include <driver/pci/pci_irq.h>
#include <common/errno.h>
#include <common/cpu.h>
#include <exception/irq.h>

View File

@ -1,7 +1,8 @@
use bitmap::{traits::BitMapOps, AllocBitmap};
use crate::mm::percpu::PerCpu;
use crate::{mm::percpu::PerCpu, smp::cpu::ProcessorId};
#[derive(Clone)]
pub struct CpuMask {
bmp: AllocBitmap,
}
@ -9,40 +10,62 @@ pub struct CpuMask {
#[allow(dead_code)]
impl CpuMask {
pub fn new() -> Self {
let bmp = AllocBitmap::new(PerCpu::MAX_CPU_NUM);
let bmp = AllocBitmap::new(PerCpu::MAX_CPU_NUM as usize);
Self { bmp }
}
/// 获取CpuMask中的第一个cpu
pub fn first(&self) -> Option<usize> {
self.bmp.first_index()
pub fn first(&self) -> Option<ProcessorId> {
self.bmp
.first_index()
.map(|index| ProcessorId::new(index as u32))
}
/// 获取CpuMask中第一个未被置位的cpu
pub fn first_zero(&self) -> Option<usize> {
self.bmp.first_false_index()
pub fn first_zero(&self) -> Option<ProcessorId> {
self.bmp
.first_false_index()
.map(|index| ProcessorId::new(index as u32))
}
/// 获取CpuMask中的最后一个被置位的cpu
pub fn last(&self) -> Option<usize> {
self.bmp.last_index()
pub fn last(&self) -> Option<ProcessorId> {
self.bmp
.last_index()
.map(|index| ProcessorId::new(index as u32))
}
/// 获取指定cpu之后第一个为1的位的cpu
pub fn next_index(&self, cpu: usize) -> Option<usize> {
self.bmp.next_index(cpu)
pub fn next_index(&self, cpu: ProcessorId) -> Option<ProcessorId> {
self.bmp
.next_index(cpu.data() as usize)
.map(|index| ProcessorId::new(index as u32))
}
/// 获取指定cpu之后第一个为未被置位的cpu
pub fn next_zero_index(&self, cpu: usize) -> Option<usize> {
self.bmp.next_false_index(cpu)
pub fn next_zero_index(&self, cpu: ProcessorId) -> Option<ProcessorId> {
self.bmp
.next_false_index(cpu.data() as usize)
.map(|index| ProcessorId::new(index as u32))
}
pub fn set(&mut self, cpu: ProcessorId, value: bool) -> Option<bool> {
self.bmp.set(cpu.data() as usize, value)
}
pub fn get(&self, cpu: ProcessorId) -> Option<bool> {
self.bmp.get(cpu.data() as usize)
}
pub fn is_empty(&self) -> bool {
self.bmp.is_empty()
}
/// 迭代所有被置位的cpu
pub fn iter_cpu(&self) -> CpuMaskIter {
CpuMaskIter {
mask: self,
index: 0,
index: ProcessorId::new(0),
set: true,
}
}
@ -51,7 +74,7 @@ impl CpuMask {
pub fn iter_zero_cpu(&self) -> CpuMaskIter {
CpuMaskIter {
mask: self,
index: 0,
index: ProcessorId::new(0),
set: false,
}
}
@ -59,15 +82,15 @@ impl CpuMask {
pub struct CpuMaskIter<'a> {
mask: &'a CpuMask,
index: usize,
index: ProcessorId,
set: bool,
}
impl<'a> Iterator for CpuMaskIter<'a> {
type Item = usize;
type Item = ProcessorId;
fn next(&mut self) -> Option<Self::Item> {
if self.index == 0 {
fn next(&mut self) -> Option<ProcessorId> {
if self.index.data() == 0 {
if self.set {
self.index = self.mask.first()?;
} else {
@ -83,3 +106,11 @@ impl<'a> Iterator for CpuMaskIter<'a> {
Some(self.index)
}
}
impl core::fmt::Debug for CpuMask {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("CpuMask")
.field("bmp", &format!("size: {}", self.bmp.size()))
.finish()
}
}

View File

@ -27,7 +27,7 @@
#[macro_export]
macro_rules! int_like {
($new_type_name:ident, $backing_type: ident) => {
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy, Hash)]
pub struct $new_type_name($backing_type);
impl $new_type_name {

View File

@ -1029,7 +1029,7 @@ pub fn textui_putchar(
if unsafe { TEXTUI_IS_INIT } {
return textui_framework()
.current_window
.lock()
.lock_irqsave()
.textui_putchar_window(
character,
fr_color,
@ -1061,7 +1061,7 @@ pub fn textui_putstr(
None
};
let mut guard = window.as_ref().map(|w| w.lock());
let mut guard = window.as_ref().map(|w| w.lock_irqsave());
for character in string.chars() {
if unsafe { TEXTUI_IS_INIT } {

View File

@ -1,4 +1,4 @@
#![allow(dead_code)]
// #![allow(dead_code)]
use core::intrinsics::unlikely;
use alloc::{collections::LinkedList, sync::Arc, vec::Vec};
@ -25,6 +25,7 @@ struct InnerWaitQueue {
#[derive(Debug)]
pub struct WaitQueue(SpinLock<InnerWaitQueue>);
#[allow(dead_code)]
impl WaitQueue {
pub const INIT: WaitQueue = WaitQueue(SpinLock::new(InnerWaitQueue::INIT));
@ -275,6 +276,7 @@ pub struct EventWaitQueue {
wait_list: SpinLock<Vec<(u64, Arc<ProcessControlBlock>)>>,
}
#[allow(dead_code)]
impl EventWaitQueue {
pub fn new() -> Self {
Self {

View File

@ -8,9 +8,11 @@ use crate::{
},
exception::InterruptArch,
libs::align::page_align_up,
mm::allocator::page_frame::PageFrameCount,
mm::{MMArch, MemoryManagementArch},
smp::core::smp_get_processor_id,
mm::{allocator::page_frame::PageFrameCount, MMArch, MemoryManagementArch},
smp::{
core::smp_get_processor_id,
cpu::{AtomicProcessorId, ProcessorId},
},
};
use core::{
ops::Deref,
@ -18,10 +20,11 @@ use core::{
};
/// 标志当前没有处理器持有内核映射器的锁
/// 之所以需要这个标志,是因为AtomicUsize::new(0)会把0当作一个处理器的id
const KERNEL_MAPPER_NO_PROCESSOR: usize = !0;
/// 之所以需要这个标志,是因为 AtomicProcessorId::new(0) 会把0当作一个处理器的id
const KERNEL_MAPPER_NO_PROCESSOR: ProcessorId = ProcessorId::INVALID;
/// 当前持有内核映射器锁的处理器
static KERNEL_MAPPER_LOCK_OWNER: AtomicUsize = AtomicUsize::new(KERNEL_MAPPER_NO_PROCESSOR);
static KERNEL_MAPPER_LOCK_OWNER: AtomicProcessorId =
AtomicProcessorId::new(KERNEL_MAPPER_NO_PROCESSOR);
/// 内核映射器的锁计数器
static KERNEL_MAPPER_LOCK_COUNT: AtomicUsize = AtomicUsize::new(0);
@ -33,7 +36,7 @@ pub struct KernelMapper {
}
impl KernelMapper {
fn lock_cpu(cpuid: usize, mapper: PageMapper) -> Self {
fn lock_cpu(cpuid: ProcessorId, mapper: PageMapper) -> Self {
loop {
match KERNEL_MAPPER_LOCK_OWNER.compare_exchange_weak(
KERNEL_MAPPER_NO_PROCESSOR,
@ -61,7 +64,7 @@ impl KernelMapper {
/// @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::Kernel, LockedFrameAllocator) };
return Self::lock_cpu(cpuid, mapper);
}

View File

@ -1,4 +1,4 @@
use core::sync::atomic::AtomicUsize;
use core::sync::atomic::AtomicU32;
use alloc::vec::Vec;
@ -11,13 +11,13 @@ use crate::{
///
/// todo: 待smp模块重构后从smp模块获取CPU数量。
/// 目前由于smp模块初始化时机较晚导致大部分内核模块无法在早期初始化PerCpu变量。
const CPU_NUM: AtomicUsize = AtomicUsize::new(PerCpu::MAX_CPU_NUM);
const CPU_NUM: AtomicU32 = AtomicU32::new(PerCpu::MAX_CPU_NUM);
#[derive(Debug)]
pub struct PerCpu;
impl PerCpu {
pub const MAX_CPU_NUM: usize = 128;
pub const MAX_CPU_NUM: u32 = 128;
/// # 初始化PerCpu
///
/// 该函数应该在内核初始化时调用一次。
@ -28,7 +28,7 @@ impl PerCpu {
if CPU_NUM.load(core::sync::atomic::Ordering::SeqCst) != 0 {
panic!("PerCpu::init() called twice");
}
let cpus = unsafe { smp_get_total_cpu() } as usize;
let cpus = unsafe { smp_get_total_cpu() };
assert!(cpus > 0, "PerCpu::init(): smp_get_total_cpu() returned 0");
CPU_NUM.store(cpus, core::sync::atomic::Ordering::SeqCst);
}
@ -62,7 +62,7 @@ impl<T> PerCpuVar<T> {
panic!("PerCpu::init() not called");
}
if data.len() != cpu_num {
if data.len() != cpu_num.try_into().unwrap() {
return None;
}
@ -76,12 +76,12 @@ impl<T> PerCpuVar<T> {
pub fn get(&self) -> &T {
let cpu_id = smp_get_processor_id();
&self.inner[cpu_id as usize]
&self.inner[cpu_id.data() as usize]
}
pub fn get_mut(&mut self) -> &mut T {
let cpu_id = smp_get_processor_id();
&mut self.inner[cpu_id as usize]
&mut self.inner[cpu_id.data() as usize]
}
}

View File

@ -18,7 +18,7 @@ unsafe extern "C" fn rs_get_idle_stack_top(cpu_id: u32) -> usize {
#[no_mangle]
unsafe extern "C" fn rs_current_pcb_cpuid() -> u32 {
return smp_get_processor_id();
return smp_get_processor_id().data();
}
#[no_mangle]

View File

@ -8,7 +8,7 @@ use alloc::{sync::Arc, vec::Vec};
use crate::{
mm::{percpu::PerCpu, VirtAddr, INITIAL_PROCESS_ADDRESS_SPACE},
process::KernelStack,
smp::core::smp_get_processor_id,
smp::{core::smp_get_processor_id, cpu::ProcessorId},
};
use super::{ProcessControlBlock, ProcessManager};
@ -27,10 +27,10 @@ impl ProcessManager {
}
assert!(
smp_get_processor_id() == 0,
smp_get_processor_id() == ProcessorId::new(0),
"Idle process must be initialized on the first processor"
);
let mut v: Vec<Arc<ProcessControlBlock>> = Vec::with_capacity(PerCpu::MAX_CPU_NUM);
let mut v: Vec<Arc<ProcessControlBlock>> = Vec::with_capacity(PerCpu::MAX_CPU_NUM as usize);
for i in 0..PerCpu::MAX_CPU_NUM {
let kstack = if unlikely(i == 0) {
@ -57,7 +57,7 @@ impl ProcessManager {
};
assert!(idle_pcb.sched_info().on_cpu().is_none());
idle_pcb.sched_info().set_on_cpu(Some(i as u32));
idle_pcb.sched_info().set_on_cpu(Some(ProcessorId::new(i)));
v.push(idle_pcb);
}

View File

@ -14,7 +14,7 @@ use system_error::SystemError;
use crate::{
arch::{sched::sched, CurrentIrqArch},
exception::InterruptArch,
exception::{irqdesc::IrqAction, InterruptArch},
init::initial_kthread::initial_kernel_thread,
kdebug, kinfo,
libs::{once::Once, spinlock::SpinLock},
@ -87,15 +87,31 @@ impl KernelThreadPcbPrivate {
#[allow(dead_code)]
pub enum KernelThreadClosure {
UsizeClosure((Box<dyn Fn(usize) -> i32 + Send + Sync>, usize)),
StaticUsizeClosure((&'static dyn Fn(usize) -> i32, usize)),
EmptyClosure((Box<dyn Fn() -> i32 + Send + Sync>, ())),
StaticEmptyClosure((&'static dyn Fn() -> i32, ())),
IrqThread(
(
&'static dyn Fn(Arc<IrqAction>) -> Result<(), SystemError>,
Arc<IrqAction>,
),
),
// 添加其他类型入参的闭包返回值必须是i32
}
unsafe impl Send for KernelThreadClosure {}
unsafe impl Sync for KernelThreadClosure {}
impl KernelThreadClosure {
pub fn run(self) -> i32 {
match self {
Self::UsizeClosure((func, arg)) => func(arg),
Self::EmptyClosure((func, _arg)) => func(),
Self::StaticUsizeClosure((func, arg)) => func(arg),
Self::StaticEmptyClosure((func, _arg)) => func(),
Self::IrqThread((func, arg)) => {
func(arg).map(|_| 0).unwrap_or_else(|e| e.to_posix_errno())
}
}
}
}

View File

@ -1,9 +1,9 @@
use core::{
hash::{Hash, Hasher},
hash::Hash,
hint::spin_loop,
intrinsics::{likely, unlikely},
mem::ManuallyDrop,
sync::atomic::{compiler_fence, AtomicBool, AtomicI32, AtomicIsize, AtomicUsize, Ordering},
sync::atomic::{compiler_fence, AtomicBool, AtomicIsize, AtomicUsize, Ordering},
};
use alloc::{
@ -48,7 +48,10 @@ use crate::{
core::{sched_enqueue, CPU_EXECUTING},
SchedPolicy, SchedPriority,
},
smp::kick_cpu,
smp::{
cpu::{AtomicProcessorId, ProcessorId},
kick_cpu,
},
syscall::{user_access::clear_user, Syscall},
};
@ -446,12 +449,6 @@ pub unsafe extern "C" fn switch_finish_hook() {
int_like!(Pid, AtomicPid, usize, AtomicUsize);
impl Hash for Pid {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}
impl Pid {
pub fn to_string(&self) -> String {
self.0.to_string()
@ -1019,10 +1016,10 @@ impl ProcessBasicInfo {
#[derive(Debug)]
pub struct ProcessSchedulerInfo {
/// 当前进程所在的cpu
on_cpu: AtomicI32,
on_cpu: AtomicProcessorId,
/// 如果当前进程等待被迁移到另一个cpu核心上也就是flags中的PF_NEED_MIGRATE被置位
/// 该字段存储要被迁移到的目标处理器核心号
migrate_to: AtomicI32,
migrate_to: AtomicProcessorId,
inner_locked: RwLock<InnerSchedInfo>,
/// 进程的调度优先级
priority: SchedPriority,
@ -1056,14 +1053,11 @@ impl InnerSchedInfo {
impl ProcessSchedulerInfo {
#[inline(never)]
pub fn new(on_cpu: Option<u32>) -> Self {
let cpu_id = match on_cpu {
Some(cpu_id) => cpu_id as i32,
None => -1,
};
pub fn new(on_cpu: Option<ProcessorId>) -> Self {
let cpu_id = on_cpu.unwrap_or(ProcessorId::INVALID);
return Self {
on_cpu: AtomicI32::new(cpu_id),
migrate_to: AtomicI32::new(-1),
on_cpu: AtomicProcessorId::new(cpu_id),
migrate_to: AtomicProcessorId::new(ProcessorId::INVALID),
inner_locked: RwLock::new(InnerSchedInfo {
state: ProcessState::Blocked(false),
sched_policy: SchedPolicy::CFS,
@ -1074,37 +1068,38 @@ impl ProcessSchedulerInfo {
};
}
pub fn on_cpu(&self) -> Option<u32> {
pub fn on_cpu(&self) -> Option<ProcessorId> {
let on_cpu = self.on_cpu.load(Ordering::SeqCst);
if on_cpu == -1 {
if on_cpu == ProcessorId::INVALID {
return None;
} else {
return Some(on_cpu as u32);
return Some(on_cpu);
}
}
pub fn set_on_cpu(&self, on_cpu: Option<u32>) {
pub fn set_on_cpu(&self, on_cpu: Option<ProcessorId>) {
if let Some(cpu_id) = on_cpu {
self.on_cpu.store(cpu_id as i32, Ordering::SeqCst);
self.on_cpu.store(cpu_id, Ordering::SeqCst);
} else {
self.on_cpu.store(-1, Ordering::SeqCst);
self.on_cpu.store(ProcessorId::INVALID, Ordering::SeqCst);
}
}
pub fn migrate_to(&self) -> Option<u32> {
pub fn migrate_to(&self) -> Option<ProcessorId> {
let migrate_to = self.migrate_to.load(Ordering::SeqCst);
if migrate_to == -1 {
if migrate_to == ProcessorId::INVALID {
return None;
} else {
return Some(migrate_to as u32);
return Some(migrate_to);
}
}
pub fn set_migrate_to(&self, migrate_to: Option<u32>) {
pub fn set_migrate_to(&self, migrate_to: Option<ProcessorId>) {
if let Some(data) = migrate_to {
self.migrate_to.store(data as i32, Ordering::SeqCst);
self.migrate_to.store(data, Ordering::SeqCst);
} else {
self.migrate_to.store(-1, Ordering::SeqCst)
self.migrate_to
.store(ProcessorId::INVALID, Ordering::SeqCst)
}
}

View File

@ -13,7 +13,6 @@
#include <common/cpu.h>
#include <common/errno.h>
#include <common/glib.h>
#include <filesystem/vfs/VFS.h>
#include <syscall/syscall.h>
/**

View File

@ -8,6 +8,22 @@ use crate::{
process::{Pid, ProcessManager},
};
use super::{ProcessFlags, __PROCESS_MANAGEMENT_INIT_DONE};
pub fn current_pcb_flags() -> ProcessFlags {
if unsafe { !__PROCESS_MANAGEMENT_INIT_DONE } {
return ProcessFlags::empty();
}
return ProcessManager::current_pcb().flags().clone();
}
pub fn current_pcb_preempt_count() -> usize {
if unsafe { !__PROCESS_MANAGEMENT_INIT_DONE } {
return 0;
}
return ProcessManager::current_pcb().preempt_count();
}
/// @brief 初始化pid=1的进程的stdio
pub fn stdio_init() -> Result<(), SystemError> {
if ProcessManager::current_pcb().pid() != Pid(1) {

View File

@ -14,7 +14,7 @@ use crate::{
process::{
ProcessControlBlock, ProcessFlags, ProcessManager, ProcessSchedulerInfo, ProcessState,
},
smp::core::smp_get_processor_id,
smp::{core::smp_get_processor_id, cpu::ProcessorId},
};
use super::{
@ -150,7 +150,8 @@ impl SchedulerCFS {
/// @brief 时钟中断到来时由sched的core模块中的函数调用本函数更新CFS进程的可执行时间
pub fn timer_update_jiffies(&mut self, sched_info: &ProcessSchedulerInfo) {
let current_cpu_queue: &mut CFSQueue = self.cpu_queue[smp_get_processor_id() as usize];
let current_cpu_queue: &mut CFSQueue =
self.cpu_queue[smp_get_processor_id().data() as usize];
// todo: 引入调度周期以及所有进程的优先权进行计算,然后设置进程的可执行时间
let mut queue = None;
@ -180,7 +181,7 @@ impl SchedulerCFS {
/// @brief 将进程加入cpu的cfs调度队列并且重设其虚拟运行时间为当前队列的最小值
pub fn enqueue_reset_vruntime(&mut self, pcb: Arc<ProcessControlBlock>) {
let cpu_queue = &mut self.cpu_queue[pcb.sched_info().on_cpu().unwrap() as usize];
let cpu_queue = &mut self.cpu_queue[pcb.sched_info().on_cpu().unwrap().data() as usize];
let queue = cpu_queue.locked_queue.lock_irqsave();
if queue.len() > 0 {
pcb.sched_info()
@ -197,8 +198,10 @@ impl SchedulerCFS {
self.cpu_queue[cpu_id].idle_pcb = pcb;
}
/// 获取某个cpu的运行队列中的进程数
pub fn get_cfs_queue_len(&mut self, cpu_id: u32) -> usize {
let queue = self.cpu_queue[cpu_id as usize].locked_queue.lock_irqsave();
pub fn get_cfs_queue_len(&mut self, cpu_id: ProcessorId) -> usize {
let queue = self.cpu_queue[cpu_id.data() as usize]
.locked_queue
.lock_irqsave();
return CFSQueue::get_cfs_queue_size(&queue);
}
}
@ -213,7 +216,7 @@ impl Scheduler for SchedulerCFS {
.flags()
.remove(ProcessFlags::NEED_SCHEDULE);
let current_cpu_id = smp_get_processor_id() as usize;
let current_cpu_id = smp_get_processor_id().data() as usize;
let current_cpu_queue: &mut CFSQueue = self.cpu_queue[current_cpu_id];
@ -272,7 +275,7 @@ impl Scheduler for SchedulerCFS {
}
fn enqueue(&mut self, pcb: Arc<ProcessControlBlock>) {
let cpu_queue = &mut self.cpu_queue[pcb.sched_info().on_cpu().unwrap() as usize];
let cpu_queue = &mut self.cpu_queue[pcb.sched_info().on_cpu().unwrap().data() as usize];
cpu_queue.enqueue(pcb);
}

View File

@ -10,7 +10,7 @@ use crate::{
kinfo,
mm::percpu::PerCpu,
process::{AtomicPid, Pid, ProcessControlBlock, ProcessFlags, ProcessManager, ProcessState},
smp::core::smp_get_processor_id,
smp::{core::smp_get_processor_id, cpu::ProcessorId},
};
use super::rt::{sched_rt_init, SchedulerRT, __get_rt_scheduler};
@ -39,23 +39,23 @@ impl CpuExecuting {
}
#[inline(always)]
pub fn set(&self, cpu_id: u32, pid: Pid) {
self.data[cpu_id as usize].store(pid, Ordering::SeqCst);
pub fn set(&self, cpu_id: ProcessorId, pid: Pid) {
self.data[cpu_id.data() as usize].store(pid, Ordering::SeqCst);
}
#[inline(always)]
pub fn get(&self, cpu_id: u32) -> Pid {
self.data[cpu_id as usize].load(Ordering::SeqCst)
pub fn get(&self, cpu_id: ProcessorId) -> Pid {
self.data[cpu_id.data() as usize].load(Ordering::SeqCst)
}
}
// 获取某个cpu的负载情况返回当前负载cpu_id 是获取负载的cpu的id
// TODO:将获取负载情况调整为最近一段时间运行进程的数量
pub fn get_cpu_loads(cpu_id: u32) -> u32 {
pub fn get_cpu_loads(cpu_id: ProcessorId) -> u32 {
let cfs_scheduler = __get_cfs_scheduler();
let rt_scheduler = __get_rt_scheduler();
let len_cfs = cfs_scheduler.get_cfs_queue_len(cpu_id as u32);
let len_rt = rt_scheduler.rt_queue_len(cpu_id as u32);
let len_cfs = cfs_scheduler.get_cfs_queue_len(cpu_id);
let len_rt = rt_scheduler.rt_queue_len(cpu_id);
// let load_rt = rt_scheduler.get_load_list_len(cpu_id);
// kdebug!("this cpu_id {} is load rt {}", cpu_id, load_rt);
@ -70,6 +70,7 @@ pub fn loads_balance(pcb: Arc<ProcessControlBlock>) {
let mut min_loads_cpu_id = smp_get_processor_id();
let mut min_loads = get_cpu_loads(smp_get_processor_id());
for cpu_id in 0..cpu_num {
let cpu_id = ProcessorId::new(cpu_id);
let tmp_cpu_loads = get_cpu_loads(cpu_id);
if min_loads - tmp_cpu_loads > 0 {
min_loads_cpu_id = cpu_id;

Some files were not shown because too many files have changed in this diff Show More