软中断处理机制

This commit is contained in:
fslongjin
2022-04-08 20:04:12 +08:00
parent d887f9a0f7
commit 9828aff985
12 changed files with 202 additions and 25 deletions

View File

@ -69,6 +69,9 @@ apu_boot.o: smp/apu_boot.S
cpu.o: common/cpu.c cpu.o: common/cpu.c
gcc $(CFLAGS) -c common/cpu.c -o common/cpu.o gcc $(CFLAGS) -c common/cpu.c -o common/cpu.o
softirq.o: exception/softirq.c
gcc $(CFLAGS) -c exception/softirq.c -o exception/softirq.o
# IPI的代码 # IPI的代码
ifeq ($(ARCH), x86_64) ifeq ($(ARCH), x86_64)
OBJ_LIST += ipi.o OBJ_LIST += ipi.o
@ -115,16 +118,19 @@ rtc.o: driver/timers/rtc/rtc.c
HPET.o: driver/timers/HPET/HPET.c HPET.o: driver/timers/HPET/HPET.c
gcc $(CFLAGS) -c driver/timers/HPET/HPET.c -o driver/timers/HPET/HPET.o gcc $(CFLAGS) -c driver/timers/HPET/HPET.c -o driver/timers/HPET/HPET.o
timer.o: driver/timers/timer.c
gcc $(CFLAGS) -c driver/timers/timer.c -o driver/timers/timer.o
all: kernel all: kernel
objcopy -I elf64-x86-64 -O elf64-x86-64 -R ".comment" -R ".eh_frame" kernel ../bin/kernel/kernel.elf objcopy -I elf64-x86-64 -O elf64-x86-64 -R ".comment" -R ".eh_frame" kernel ../bin/kernel/kernel.elf
# #
kernel: head.o entry.o main.o printk.o trap.o mm.o slab.o irq.o pic.o process.o syscall.o multiboot2.o cpu.o acpi.o ps2_keyboard.o ps2_mouse.o ata.o pci.o ahci.o smp.o apu_boot.o rtc.o HPET.o $(OBJ_LIST) kernel: head.o entry.o main.o printk.o trap.o mm.o slab.o irq.o pic.o process.o syscall.o multiboot2.o cpu.o acpi.o ps2_keyboard.o ps2_mouse.o ata.o pci.o ahci.o smp.o apu_boot.o rtc.o HPET.o softirq.o timer.o $(OBJ_LIST)
ld -b elf64-x86-64 -z muldefs -o kernel head.o exception/entry.o main.o common/printk.o exception/trap.o exception/irq.o mm/mm.o mm/slab.o process/process.o syscall/syscall.o driver/multiboot2/multiboot2.o \ ld -b elf64-x86-64 -z muldefs -o kernel head.o exception/entry.o main.o common/printk.o exception/trap.o exception/irq.o mm/mm.o mm/slab.o process/process.o syscall/syscall.o driver/multiboot2/multiboot2.o \
common/cpu.o smp/smp.o smp/apu_boot.o \ common/cpu.o smp/smp.o smp/apu_boot.o exception/softirq.o \
driver/acpi/acpi.o driver/interrupt/pic.o driver/keyboard/ps2_keyboard.o driver/mouse/ps2_mouse.o driver/disk/ata.o driver/pci/pci.o driver/disk/ahci/ahci.o driver/timers/rtc/rtc.o driver/timers/HPET/HPET.o \ driver/acpi/acpi.o driver/interrupt/pic.o driver/keyboard/ps2_keyboard.o driver/mouse/ps2_mouse.o driver/disk/ata.o driver/pci/pci.o driver/disk/ahci/ahci.o driver/timers/rtc/rtc.o driver/timers/HPET/HPET.o driver/timers/timer.o \
$(LD_LIST) \ $(LD_LIST) \
-T link.lds -T link.lds

View File

@ -393,3 +393,14 @@ ul rdmsr(ul address)
: "memory"); : "memory");
return ((ul)tmp0 << 32) | tmp1; return ((ul)tmp0 << 32) | tmp1;
} }
uint64_t get_rflags()
{
unsigned long tmp = 0;
__asm__ __volatile__ ("pushfq \n\t"
"movq (%%rsp), %0 \n\t"
"popfq \n\t"
:"=r"(tmp)::"memory");
return tmp;
}

View File

@ -36,7 +36,6 @@ int printk_init(const int char_size_x, const int char_size_y)
pos.max_x = calculate_max_charNum(pos.width, char_size_x); pos.max_x = calculate_max_charNum(pos.width, char_size_x);
pos.max_y = calculate_max_charNum(pos.height, char_size_y); pos.max_y = calculate_max_charNum(pos.height, char_size_y);
VBE_FB_phys_addr = (ul)info.framebuffer_addr; VBE_FB_phys_addr = (ul)info.framebuffer_addr;
pos.FB_address = (uint *)0x0000000003000000; pos.FB_address = (uint *)0x0000000003000000;
pos.FB_length = 1UL * pos.width * pos.height; pos.FB_length = 1UL * pos.width * pos.height;
@ -75,8 +74,6 @@ int printk_init(const int char_size_x, const int char_size_y)
kdebug("width=%d\theight=%d", pos.width, pos.height); kdebug("width=%d\theight=%d", pos.width, pos.height);
while (1)
return 0; return 0;
} }
@ -655,7 +652,10 @@ int printk_color(unsigned int FRcolor, unsigned int BKcolor, const char *fmt, ..
* @param ... 格式化字符串 * @param ... 格式化字符串
*/ */
spin_lock(&printk_lock); /*
if (get_rflags() & 0x200UL)
spin_lock(&printk_lock); // 不是中断处理程序调用printk加锁
*/
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
@ -712,8 +712,10 @@ int printk_color(unsigned int FRcolor, unsigned int BKcolor, const char *fmt, ..
} }
} }
for(int j=0;j<1e5;++j); /*
if (get_rflags() & 0x200UL)
spin_unlock(&printk_lock); spin_unlock(&printk_lock);
*/
return i; return i;
} }

View File

@ -6,6 +6,8 @@
#include "../../../exception/gate.h" #include "../../../exception/gate.h"
#include "../../acpi/acpi.h" #include "../../acpi/acpi.h"
#include <exception/softirq.h>
// 导出定义在irq.c中的中段门表 // 导出定义在irq.c中的中段门表
extern void (*interrupt_table[24])(void); extern void (*interrupt_table[24])(void);
@ -389,9 +391,9 @@ void apic_local_apic_init()
*/ */
void apic_init() void apic_init()
{ {
// 初始化中断门, 中断使用第二个ist // 初始化中断门, 中断使用rsp0防止在软中断时发生嵌套然后处理器重新加载导致数据被抹掉
for (int i = 32; i <= 55; ++i) for (int i = 32; i <= 55; ++i)
set_intr_gate(i, 2, interrupt_table[i - 32]); set_intr_gate(i, 0, interrupt_table[i - 32]);
// 初始化主芯片 // 初始化主芯片
io_out8(0x20, 0x11); // 初始化主芯片的icw1 io_out8(0x20, 0x11); // 初始化主芯片的icw1
io_out8(0x21, 0x20); // 设置主芯片的中断向量号为0x20(0x20-0x27) io_out8(0x21, 0x20); // 设置主芯片的中断向量号为0x20(0x20-0x27)
@ -466,6 +468,10 @@ void do_IRQ(struct pt_regs *rsp, ul number)
kwarn("do IRQ receive: %d", number); kwarn("do IRQ receive: %d", number);
break; break;
} }
// 检测是否有未处理的软中断
if (softirq_status != 0)
do_softirq();
} }
/** /**

View File

@ -2,6 +2,8 @@
#include <common/kprint.h> #include <common/kprint.h>
#include <mm/mm.h> #include <mm/mm.h>
#include <driver/interrupt/apic/apic.h> #include <driver/interrupt/apic/apic.h>
#include <exception/softirq.h>
#include <driver/timers/timer.h>
static struct acpi_HPET_description_table_t *hpet_table; static struct acpi_HPET_description_table_t *hpet_table;
static uint64_t HPET_REG_BASE = 0; static uint64_t HPET_REG_BASE = 0;
@ -46,14 +48,15 @@ hardware_intr_controller HPET_intr_controller =
void HPET_handler(uint64_t number, uint64_t param, struct pt_regs *regs) void HPET_handler(uint64_t number, uint64_t param, struct pt_regs *regs)
{ {
//printk_color(ORANGE, BLACK, "(HPET)");
switch (param) switch (param)
{ {
case 0: case 0: // 定时器0中断
rtc_get_cmos_time(&rtc_now); ++timer_jiffies;
set_softirq_status(TIMER_SIRQ);
break; break;
default: default:
kwarn("Unsupported HPET irq: %d.", number);
break; break;
} }
} }
@ -97,6 +100,4 @@ int HPET_init()
rtc_get_cmos_time(&rtc_now); rtc_get_cmos_time(&rtc_now);
*(uint64_t *)(HPET_REG_BASE + MAIN_CNT) = 0; *(uint64_t *)(HPET_REG_BASE + MAIN_CNT) = 0;
io_mfence(); io_mfence();
} }

View File

@ -17,3 +17,5 @@ struct rtc_time_t
* @return int 成功则为0 * @return int 成功则为0
*/ */
int rtc_get_cmos_time(struct rtc_time_t*t); int rtc_get_cmos_time(struct rtc_time_t*t);
void rtc_init();

View File

@ -0,0 +1,14 @@
#include "timer.h"
#include<common/kprint.h>
#include <exception/softirq.h>
void timer_init()
{
timer_jiffies = 0;
register_softirq(0, &do_timer_softirq, NULL);
}
void do_timer_softirq(void* data)
{
printk_color(ORANGE, BLACK, "(HPET%ld)", timer_jiffies);
}

View File

@ -0,0 +1,11 @@
#pragma once
#include <common/glib.h>
#include "HPET/HPET.h"
#include "rtc/rtc.h"
uint64_t volatile timer_jiffies = 0; // 系统时钟计数
void timer_init();
void do_timer_softirq(void* data);

View File

@ -50,7 +50,6 @@ Restore_all:
popq %rax popq %rax
addq $0x10, %rsp // FUNCerrcode addq $0x10, %rsp // FUNCerrcode
iretq iretq
ret_from_exception: ret_from_exception:
@ -58,6 +57,7 @@ ret_from_exception:
ENTRY(ret_from_intr) ENTRY(ret_from_intr)
jmp Restore_all jmp Restore_all
Err_Code: Err_Code:
// ===== // =====

View File

@ -0,0 +1,65 @@
#include "softirq.h"
#include <common/kprint.h>
void set_softirq_status(uint64_t status)
{
softirq_status |= status;
}
uint64_t get_softirq_status()
{
return softirq_status;
}
/**
* @brief 软中断注册函数
*
* @param irq_num 软中断号
* @param action 响应函数
* @param data 响应数据结构体
*/
void register_softirq(uint32_t irq_num, void (*action)(void *data), void *data)
{
softirq_vector[irq_num].action = action;
softirq_vector[irq_num].data = data;
}
/**
* @brief 卸载软中断
*
* @param irq_num 软中断号
*/
void unregister_softirq(uint32_t irq_num)
{
softirq_vector[irq_num].action = NULL;
softirq_vector[irq_num].data = NULL;
}
/**
* @brief 软中断处理程序
*
*/
void do_softirq()
{
sti();
for(uint32_t i=0;i<MAX_SOFTIRQ_NUM&&softirq_status;++i)
{
if(softirq_status&(1<<i))
{
softirq_vector[i].action(softirq_vector[i].data);
softirq_status &= (~(1<<i));
}
}
cli();
}
void softirq_init()
{
softirq_status = 0;
memset(softirq_vector, 0, sizeof(struct softirq_t) * MAX_SOFTIRQ_NUM);
}

View File

@ -0,0 +1,56 @@
/**
* @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>
#define MAX_SOFTIRQ_NUM 64
#define TIMER_SIRQ (1<<0) // 时钟软中断号
uint64_t softirq_status = 0;
struct softirq_t
{
void (*action)(void* data); // 软中断处理函数
void* data;
};
struct softirq_t softirq_vector[MAX_SOFTIRQ_NUM] = {0};
/**
* @brief 软中断注册函数
*
* @param irq_num 软中断号
* @param action 响应函数
* @param data 响应数据结构体
*/
void register_softirq(uint32_t irq_num, void (*action)(void * data), void* data);
/**
* @brief 卸载软中断
*
* @param irq_num 软中断号
*/
void unregister_softirq(uint32_t irq_num);
void set_softirq_status(uint64_t status);
uint64_t get_softirq_status();
/**
* @brief 软中断处理程序
*
*/
void do_softirq();
void softirq_init();

View File

@ -8,6 +8,7 @@
#include "exception/gate.h" #include "exception/gate.h"
#include "exception/trap.h" #include "exception/trap.h"
#include "exception/irq.h" #include "exception/irq.h"
#include <exception/softirq.h>
#include "mm/mm.h" #include "mm/mm.h"
#include "mm/slab.h" #include "mm/slab.h"
#include "process/process.h" #include "process/process.h"
@ -24,6 +25,7 @@
#include "driver/disk/ahci/ahci.h" #include "driver/disk/ahci/ahci.h"
#include <driver/timers/rtc/rtc.h> #include <driver/timers/rtc/rtc.h>
#include <driver/timers/HPET/HPET.h> #include <driver/timers/HPET/HPET.h>
#include <driver/timers/timer.h>
unsigned int *FR_address = (unsigned int *)0xb8000; //帧缓存区的地址 unsigned int *FR_address = (unsigned int *)0xb8000; //帧缓存区的地址
@ -167,9 +169,9 @@ void system_initialize()
acpi_init(); acpi_init();
// 初始化中断模块 // 初始化中断模块
irq_init(); irq_init();
softirq_init();
timer_init();
HPET_init(); HPET_init();
smp_init(); smp_init();
// 先初始化系统调用模块 // 先初始化系统调用模块
@ -181,7 +183,6 @@ void system_initialize()
// ata_init(); // ata_init();
pci_init(); pci_init();
ahci_init(); ahci_init();
// test_slab(); // test_slab();
// test_mm(); // test_mm();
@ -233,6 +234,7 @@ void Start_Kernel(void)
// ipi_send_IPI(DEST_PHYSICAL, IDLE, ICR_LEVEL_DE_ASSERT, EDGE_TRIGGER, 0xc8, ICR_APIC_FIXED, ICR_No_Shorthand, true, 1); // 测试ipi // ipi_send_IPI(DEST_PHYSICAL, IDLE, ICR_LEVEL_DE_ASSERT, EDGE_TRIGGER, 0xc8, ICR_APIC_FIXED, ICR_No_Shorthand, true, 1); // 测试ipi
int last_sec = rtc_now.second; int last_sec = rtc_now.second;
/*
while (1) while (1)
{ {
if (last_sec != rtc_now.second) if (last_sec != rtc_now.second)
@ -241,6 +243,7 @@ void Start_Kernel(void)
kinfo("Current Time: %04d/%02d/%02d %02d:%02d:%02d", rtc_now.year, rtc_now.month, rtc_now.day, rtc_now.hour, rtc_now.minute, rtc_now.second); kinfo("Current Time: %04d/%02d/%02d %02d:%02d:%02d", rtc_now.year, rtc_now.month, rtc_now.day, rtc_now.hour, rtc_now.minute, rtc_now.second);
} }
} }
*/
while (1) while (1)
hlt(); hlt();
} }