Parcourir la source

软中断处理机制

fslongjin il y a 2 ans
Parent
commit
9828aff985

+ 9 - 3
kernel/Makefile

@@ -69,6 +69,9 @@ apu_boot.o: smp/apu_boot.S
 cpu.o: common/cpu.c 
 	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的代码
 ifeq ($(ARCH), x86_64)
 OBJ_LIST += ipi.o
@@ -115,16 +118,19 @@ rtc.o: driver/timers/rtc/rtc.c
 HPET.o: driver/timers/HPET/HPET.c
 	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
 	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 \
-	common/cpu.o smp/smp.o smp/apu_boot.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 \
+	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/timers/timer.o \
 	$(LD_LIST)	\
 	-T link.lds
 

+ 11 - 0
kernel/common/glib.h

@@ -393,3 +393,14 @@ ul rdmsr(ul address)
                          : "memory");
     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;
+}

+ 12 - 10
kernel/common/printk.c

@@ -36,10 +36,9 @@ 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_y = calculate_max_charNum(pos.height, char_size_y);
 
-    
     VBE_FB_phys_addr = (ul)info.framebuffer_addr;
     pos.FB_address = (uint *)0x0000000003000000;
-    pos.FB_length = 1UL*pos.width * pos.height;
+    pos.FB_length = 1UL * pos.width * pos.height;
 
     // 初始化自旋锁
     spin_init(&printk_lock);
@@ -75,9 +74,7 @@ int printk_init(const int char_size_x, const int char_size_y)
 
     kdebug("width=%d\theight=%d", pos.width, pos.height);
 
-    while (1)
-
-        return 0;
+    return 0;
 }
 
 int set_printk_pos(const int x, const int y)
@@ -120,7 +117,7 @@ void auto_newline()
         pos.y = pos.max_y;
         int lines_to_scroll = 1;
         scroll(true, lines_to_scroll * pos.char_size_y, false);
-        pos.y -= (lines_to_scroll-1);
+        pos.y -= (lines_to_scroll - 1);
     }
 }
 
@@ -654,8 +651,11 @@ int printk_color(unsigned int FRcolor, unsigned int BKcolor, const char *fmt, ..
      * @param BKcolor 背景色
      * @param ... 格式化字符串
      */
-
-    spin_lock(&printk_lock);
+    
+    /*
+    if (get_rflags() & 0x200UL)
+        spin_lock(&printk_lock); // 不是中断处理程序调用printk,加锁
+        */
 
     va_list args;
     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);
-    spin_unlock(&printk_lock);
+    /*
+    if (get_rflags() & 0x200UL)
+        spin_unlock(&printk_lock);
+        */
     return i;
 }
 

+ 8 - 2
kernel/driver/interrupt/apic/apic.c

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

+ 6 - 5
kernel/driver/timers/HPET/HPET.c

@@ -2,6 +2,8 @@
 #include <common/kprint.h>
 #include <mm/mm.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 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)
 {
-    //printk_color(ORANGE, BLACK, "(HPET)");
     switch (param)
     {
-    case 0:
-        rtc_get_cmos_time(&rtc_now);
+    case 0: // 定时器0中断
+        ++timer_jiffies;
+        set_softirq_status(TIMER_SIRQ);
         break;
 
     default:
+        kwarn("Unsupported HPET irq: %d.", number);
         break;
     }
 }
@@ -97,6 +100,4 @@ int HPET_init()
     rtc_get_cmos_time(&rtc_now);
     *(uint64_t *)(HPET_REG_BASE + MAIN_CNT) = 0;
     io_mfence();
-
-    
 }

+ 3 - 1
kernel/driver/timers/rtc/rtc.h

@@ -16,4 +16,6 @@ struct rtc_time_t
  * @param t time结构体
  * @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();

+ 14 - 0
kernel/driver/timers/timer.c

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

+ 11 - 0
kernel/driver/timers/timer.h

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

+ 1 - 1
kernel/exception/entry.S

@@ -50,7 +50,6 @@ Restore_all:
 
     popq %rax
     addq $0x10, %rsp // 弹出变量FUNC和errcode
-
     iretq
 
 ret_from_exception:
@@ -58,6 +57,7 @@ ret_from_exception:
 ENTRY(ret_from_intr)
     jmp Restore_all
 
+    
 Err_Code:
     // ===== 有错误码的情况下,保存寄存器并跳转服务程序
 

+ 65 - 0
kernel/exception/softirq.c

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

+ 56 - 0
kernel/exception/softirq.h

@@ -0,0 +1,56 @@
+/**
+ * @file softirq.h
+ * @author fslongjin ([email protected])
+ * @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();

+ 6 - 3
kernel/main.c

@@ -8,6 +8,7 @@
 #include "exception/gate.h"
 #include "exception/trap.h"
 #include "exception/irq.h"
+#include <exception/softirq.h>
 #include "mm/mm.h"
 #include "mm/slab.h"
 #include "process/process.h"
@@ -24,6 +25,7 @@
 #include "driver/disk/ahci/ahci.h"
 #include <driver/timers/rtc/rtc.h>
 #include <driver/timers/HPET/HPET.h>
+#include <driver/timers/timer.h>
 
 unsigned int *FR_address = (unsigned int *)0xb8000; //帧缓存区的地址
 
@@ -167,9 +169,9 @@ void system_initialize()
     acpi_init();
     // 初始化中断模块
     irq_init();
-
+    softirq_init();
+    timer_init();
     HPET_init();
-
     smp_init();
 
     // 先初始化系统调用模块
@@ -181,7 +183,6 @@ void system_initialize()
     // ata_init();
     pci_init();
     ahci_init();
-
     // test_slab();
     // 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
 
     int last_sec = rtc_now.second;
+    /*
     while (1)
     {
         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);
         }
     }
+    */
     while (1)
         hlt();
 }