🆕 中断上半部

This commit is contained in:
fslongjin 2022-03-15 18:41:58 +08:00
parent c187ef152a
commit d4c07ac4ad
5 changed files with 404 additions and 8 deletions

View File

@ -112,4 +112,5 @@ void acpi_init()
kdebug("acpi_RSDT_entry_phys_base=%#018lx", acpi_RSDT_entry_phys_base);
// 映射RSDT ENTRY的物理地址
mm_map_phys_addr(ACPI_DESCRIPTION_HEDERS_BASE, acpi_RSDT_entry_phys_base, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD);
kinfo("ACPI module initialized!")
}

View File

@ -74,7 +74,7 @@ void apic_io_apic_init()
// 初始化RTE表项将所有RTE表项屏蔽
for (int i = 0x10; i < 0x40; i += 2)
{
// 以0x20起始中断向量号初始化RTE
// 以0x20起始中断向量号初始化RTE
apic_ioapic_write_rte(i, 0x10020 + ((i - 0x10) >> 1));
}
@ -285,13 +285,24 @@ void apic_init()
* @brief
*
* @param rsp
* @param number
* @param number
*/
void do_IRQ(struct pt_regs *rsp, ul number)
{
unsigned char x = io_in8(0x60);
printk_color(BLUE, WHITE, "(IRQ:%#04x)\tkey code:%#04x\n", number, x);
irq_desc_t *irq = &interrupt_desc[number - 32];
// 执行中断上半部处理程序
if (irq->handler != NULL)
irq->handler(number, irq->parameter, rsp);
// 向中断控制器发送应答消息
if (irq->controller != NULL && irq->controller->ack != NULL)
irq->controller->ack(number);
// 向EOI寄存器写入0x00表示结束中断
io_mfence();
uint *eoi = (uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_EOI);
@ -348,3 +359,49 @@ void apic_ioapic_write_rte(unsigned char index, ul value)
*apic_ioapic_map.virtual_data_addr = value & 0xffffffff;
io_mfence();
}
// =========== 中断控制操作接口 ============
void apic_ioapic_enable(ul irq_num)
{
ul index = 0x10 + ((irq_num - 32) << 1);
ul value = apic_ioapic_read_rte(index);
value &= (~0x10000UL);
apic_ioapic_write_rte(index, value);
}
void apic_ioapic_disable(ul irq_num)
{
ul index = 0x10 + ((irq_num - 32) << 1);
ul value = apic_ioapic_read_rte(index);
value |= (0x10000UL);
apic_ioapic_write_rte(index, value);
}
ul apic_ioapic_install(ul irq_num, void *arg)
{
struct apic_IO_APIC_RTE_entry *entry = (struct apic_IO_APIC_RTE_entry *)arg;
// RTE表项值写入对应的RTE寄存器
apic_ioapic_write_rte(0x10 + ((irq_num - 32) << 1), *(ul *)entry);
return 0;
}
void apic_ioapic_uninstall(ul irq_num)
{
// 将对应的RTE表项设置为屏蔽状态
apic_ioapic_write_rte(0x10 + ((irq_num - 32) << 1), 0x10000UL);
}
void apic_ioapic_level_ack(ul irq_num) // 电平触发
{
// 向EOI寄存器写入0x00表示结束中断
uint *eoi = (uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_EOI);
*eoi = 0x00;
*apic_ioapic_map.virtual_EOI_addr = irq_num;
}
void apic_ioapic_edge_ack(ul irq_num) // 边沿触发
{
// 向EOI寄存器写入0x00表示结束中断
uint *eoi = (uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_EOI);
*eoi = 0x00;
}

View File

@ -70,9 +70,163 @@
// 分频配置寄存器(定时器专用)
#define LOCAL_APIC_OFFSET_Local_APIC_CLKDIV 0x3e0
/*
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
/*
ICR
*/
struct INT_CMD_REG
{
unsigned int vector : 8, // 0~7
deliver_mode : 3, // 8~10
dest_mode : 1, // 11
deliver_status : 1, // 12
res_1 : 1, // 13
level : 1, // 14
trigger : 1, // 15
res_2 : 2, // 16~17
dest_shorthand : 2, // 18~19
res_3 : 12; // 20~31
union
{
struct
{
unsigned int res_4 : 24, // 32~55
dest_field : 8; // 56~63
} apic_destination;
unsigned int x2apic_destination; // 32~63
} destination;
} __attribute__((packed));
/**
* @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 : 19; // [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 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
#define IRR_RESET 0
#define IRR_ACCEPT 1
// 电平触发极性
#define POLARITY_HIGH 0
#define POLARITY_LOW 1
struct apic_IO_APIC_map
{
@ -90,7 +244,7 @@ struct apic_IO_APIC_map
* @brief
*
* @param rsp
* @param number
* @param number
*/
void do_IRQ(struct pt_regs *rsp, ul number);
@ -115,3 +269,11 @@ void apic_ioapic_write_rte(unsigned char index, ul value);
*
*/
void apic_init();
// =========== 中断控制操作接口 ============
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_level_ack(ul irq_num); // 电平触发
void apic_ioapic_edge_ack(ul irq_num); // 边沿触发

View File

@ -111,6 +111,55 @@ void (*interrupt_table[24])(void) =
IRQ0x37interrupt,
};
/**
* @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_int_controller *controller, char *irq_name)
{
// 由于为I/O APIC分配的中断向量号是从32开始的因此要减去32才是对应的interrupt_desc的元素
irq_desc_t *p = &interrupt_desc[irq_num - 32];
p->controller = controller;
p->irq_name = irq_name;
p->parameter = paramater;
p->flags = 0;
p->handler = handler;
p->controller->install(irq_num, arg);
p->controller->enable(irq_num);
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;
p->irq_name = NULL;
p->parameter = NULL;
p->flags = 0;
p->handler = NULL;
return 0;
}
/**
* @brief
*/
@ -119,6 +168,8 @@ void irq_init()
#if _INTR_8259A_
init_8259A();
#else
memset(interrupt_desc, 0, sizeof(irq_desc_t) * IRQ_NUM);
apic_init();
#endif
}

View File

@ -15,9 +15,134 @@
#include "../process/ptrace.h"
extern void (*interrupt_table[24])(void);
extern void do_IRQ(struct pt_regs *regs, ul number);
/* ========= 中断向量分配表 ==========
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
45 FERR#
46 SATA primary
47 SATA secondary
48 PIRQA
49 PIRQB
50 PIRQC
51 PIRQD
52 PIRQE
53 PIRQF
54 PIRQG
55 PIRQH
0x80 system call
150 ~ 200 Local APIC
150 CMCI
151 Timer
152 Thermal Monitor
153 Performance Counter
154 LINT0
155 LINT1
156 Error
200 ~ 255 MP IPI
*/
typedef struct hardware_int_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_int_controller;
// 中断描述结构体
typedef struct
{
hardware_int_controller *controller;
// 中断名
char *irq_name;
// 中断处理函数的参数
ul parameter;
// 中断处理函数
void (*handler)(ul irq_num, ul parameter, struct pt_regs *regs);
// 自定义的标志位
ul flags;
} irq_desc_t;
#define IRQ_NUM 24
irq_desc_t interrupt_desc[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_int_controller *controller, char *irq_name);
/**
* @brief
*
* @param irq_num
* @return int
*/
int irq_unregister(ul irq_num);
/**
* @brief
*/
void irq_init();