Переглянути джерело

打印中断控制器结构的信息

fslongjin 3 роки тому
батько
коміт
1f3c8bc204

+ 54 - 25
kernel/driver/acpi/acpi.c

@@ -4,6 +4,9 @@
 #include "../multiboot2/multiboot2.h"
 #include "../../mm/mm.h"
 
+// 获取RSDT entry的虚拟地址
+#define acpi_get_RSDT_entry_vaddr(phys_addr) (ACPI_DESCRIPTION_HEDERS_BASE + MASK_HIGH_32bit(phys_addr) - acpi_RSDT_entry_phys_base)
+
 static struct acpi_RSDP_t *rsdpv1;
 static struct acpi_RSDP_2_t *rsdpv2;
 static struct acpi_RSDT_Structure_t *rsdt;
@@ -14,7 +17,6 @@ static struct multiboot_tag_new_acpi_t new_acpi;
 static ul acpi_RSDT_offset = 0;
 static uint acpi_RSDT_Entry_num = 0;
 
-
 // RSDT中的第一个entry所在物理页的基地址
 static ul acpi_RSDT_entry_phys_base = 0;
 
@@ -23,15 +25,61 @@ static ul acpi_RSDT_entry_phys_base = 0;
  * @param  _fun            迭代操作调用的函数
  * @param  _data           数据
  */
-void acpi_iter_SDT(bool (*_fun)(const struct acpi_iter_SDT_header_t *, void *),
+void acpi_iter_SDT(bool (*_fun)(const struct acpi_system_description_table_header_t *, void *),
                    void *_data)
 {
+
+    struct acpi_system_description_table_header_t *sdt_header;
+    uint *ent = &(rsdt->Entry);
+    for (int i = 0; i < acpi_RSDT_Entry_num; ++i)
+    {
+
+        sdt_header = (struct acpi_system_description_table_header_t *)(acpi_get_RSDT_entry_vaddr((ul)(*(ent + i))));
+
+        if (_fun(sdt_header, _data) == true)
+            return;
+    }
+
+    return;
 }
 
-static ul acpi_get_RSDT_entry_vaddr(ul phys_addr)
+/**
+ * @brief 获取MADT信息 Multiple APIC Description Table
+ *
+ * @param _iter_data 要被迭代的信息的结构体
+ * @param _data 返回信息的结构体指针
+ * @param count 返回数组的长度
+ * @return true
+ * @return false
+ */
+bool acpi_get_MADT(const struct acpi_system_description_table_header_t *_iter_data, void *_data)
 {
-    return ACPI_DESCRIPTION_HEDERS_BASE + MASK_HIGH_32bit(phys_addr) - acpi_RSDT_entry_phys_base;
+    if (!(_iter_data->Signature[0] == 'A' && _iter_data->Signature[1] == 'P' && _iter_data->Signature[2] == 'I' && _iter_data->Signature[3] == 'C'))
+        return false;
+    //*(struct acpi_Multiple_APIC_Description_Table_t *)_data = *(struct acpi_Multiple_APIC_Description_Table_t *)_iter_data;
+    *(ul*)_data = _iter_data;
+    kdebug("_iter_data = %#018lx", (ul)_iter_data);
+    kdebug("_data = %#018lx", (ul)_data);
+    //_data = _iter_data;
+    /*
+    void *ent = (void *)(_iter_data) + sizeof(struct acpi_Multiple_APIC_Description_Table_t);
+    struct apic_Interrupt_Controller_Structure_header_t *header;
+    for (int i = 0; i < 17; ++i)
+    {
+        header = (struct apic_Interrupt_Controller_Structure_header_t *)ent;
+        kdebug("[ %d ] type=%d, length=%d", i, header->type, header->length);
+        if (header->type == 1)
+        {
+            struct acpi_IO_APIC_Structure_t *t = (struct acpi_IO_APIC_Structure_t *)ent;
+            kdebug("IO apic addr = %#018lx", t->IO_APIC_Address);
+        }
+
+        ent += header->length;
+    }
+    */
+    return true;
 }
+
 /**
  * @brief 初始化acpi模块
  *
@@ -63,13 +111,12 @@ void acpi_init()
     kdebug("Rsdt_v2_phys_Address=%#018lx", rsdpv2->rsdp1.RsdtAddress);
     kdebug("RSDP_v2_Revision=%d", rsdpv2->rsdp1.Revision);
 
-    rsdt = ACPI_RSDT_VIRT_ADDR_BASE + acpi_RSDT_offset;
+    rsdt = (struct acpi_RSDT_Structure_t *)(ACPI_RSDT_VIRT_ADDR_BASE + acpi_RSDT_offset);
 
     // 计算RSDT Entry的数量
     kdebug("offset=%d", sizeof(rsdt->header));
     acpi_RSDT_Entry_num = (rsdt->header.Length - 36) / 4;
 
-    printk_color(ORANGE, BLACK, "%s\n", rsdt->header.Signature);
     printk_color(ORANGE, BLACK, "RSDT Length=%dbytes.\n", rsdt->header.Length);
     printk_color(ORANGE, BLACK, "RSDT Entry num=%d\n", acpi_RSDT_Entry_num);
 
@@ -78,26 +125,8 @@ void acpi_init()
     // 由于地址只是32bit的,并且存在脏数据,这里需要手动清除高32bit,否则会触发#GP
     acpi_RSDT_entry_phys_base = MASK_HIGH_32bit(acpi_RSDT_entry_phys_base);
 
-
     kdebug("entry=%#018lx", rsdt->Entry);
     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);
-
-    // 设置第一个entry的虚拟地址
-    struct acpi_system_description_table_header_t *sdt_header;
-    uint* ent = &(rsdt->Entry);
-    for (int i = 0; i < acpi_RSDT_Entry_num; ++i)
-    {
-        kdebug("entry_addr_phys[ %d ]= %#018lx", i, MASK_HIGH_32bit((ul)(*(ent+i))));
-        sdt_header = (struct acpi_system_description_table_header_t *)(acpi_get_RSDT_entry_vaddr((ul)(*(ent+i))));
-        if(i<7)
-        {
-            struct acpi_Multiple_APIC_Description_Table_t *madt = (struct acpi_Multiple_APIC_Description_Table_t*)sdt_header;
-            for(int j=0;j<4;++j)
-                printk_color(ORANGE, BLACK, "%c", madt->header.Signature[j]);
-            printk("\n");
-            kdebug("length=%d", madt->header.Length);
-        }
-    }
 }

+ 18 - 14
kernel/driver/acpi/acpi.h

@@ -5,6 +5,7 @@
 #pragma once
 
 #include "../../common/glib.h"
+#include "../../mm/mm.h"
 
 #define ACPI_ICS_TYPE_PROCESSOR_LOCAL_APIC 0
 #define ACPI_ICS_TYPE_IO_APIC 1
@@ -25,11 +26,9 @@
 // 0x10-0x7f Reserved. OSPM skips structures of the reserved type.
 // 0x80-0xff Reserved for OEM use
 
-#define ACPI_RSDT_VIRT_ADDR_BASE 0xffff80000a000000UL
+#define ACPI_RSDT_VIRT_ADDR_BASE SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + ACPI_RSDT_MAPPING_OFFSET
 #define ACPI_DESCRIPTION_HEDERS_BASE ACPI_RSDT_VIRT_ADDR_BASE + PAGE_2M_SIZE
 
-
-
 struct acpi_RSDP_t
 {
     unsigned char Signature[8];
@@ -85,7 +84,7 @@ struct acpi_Multiple_APIC_Description_Table_t
     // Multiple APIC flags, 详见 ACPI Specification Version 6.3, Table 5-44
     uint flags;
 
-    void *Interrupt_Controller_Structure;
+    // 接下来的(length-44)字节是Interrupt Controller Structure
 };
 
 struct apic_Interrupt_Controller_Structure_header_t
@@ -105,7 +104,7 @@ struct acpi_Processor_Local_APIC_Structure_t
     uint flags;
 };
 
-struct acpi_Processor_IO_APIC_Structure_t
+struct acpi_IO_APIC_Structure_t
 {
     // type=1
     struct apic_Interrupt_Controller_Structure_header_t header;
@@ -140,22 +139,16 @@ struct acpi_XSDT_Structure_t
     ul *Entry;
 };
 
-// 要被迭代的系统描述表的开头的sign
-struct acpi_iter_SDT_header_t
-{
-    unsigned char Signature[8];
-};
-
 /**
  * @brief 迭代器,用于迭代描述符头(位于ACPI标准文件的Table 5-29)
  * @param  _fun            迭代操作调用的函数
  * @param  _data           数据
  */
-void acpi_iter_SDT(bool (*_fun)(const struct acpi_iter_SDT_header_t *, void *),
+void acpi_iter_SDT(bool (*_fun)(const struct acpi_system_description_table_header_t *, void *),
                    void *_data);
 
 /**
- * @brief 获取MADT信息
+ * @brief 获取MADT信息 Multiple APIC Description Table
  *
  * @param _iter_data 要被迭代的信息的结构体
  * @param _data 返回信息的结构体指针
@@ -163,7 +156,18 @@ void acpi_iter_SDT(bool (*_fun)(const struct acpi_iter_SDT_header_t *, void *),
  * @return true
  * @return false
  */
-bool acpi_get_MADT(const struct acpi_iter_SDT_header_t *_iter_data, void *_data);
+bool acpi_get_MADT(const struct acpi_system_description_table_header_t *_iter_data, void *_data);
+
+
+/**
+ * @brief 迭代器,用于迭代中断控制器结构(Interrupt Controller Structure)(位于ACPI标准文件的Table 5-45)
+ * @param  _fun            迭代操作调用的函数
+ * @param  _data           数据
+ */
+void acpi_iter_Interrupt_Controller_Structure(bool (*_fun)(const struct apic_Interrupt_Controller_Structure_header_t *, void *),
+                   void *_data);
+
+
 
 // 初始化acpi模块
 void acpi_init();

+ 24 - 0
kernel/driver/interrupt/apic/apic.c

@@ -4,6 +4,7 @@
 #include "../../../common/cpu.h"
 #include "../../../common/glib.h"
 #include "../../../exception/gate.h"
+#include "../../acpi/acpi.h"
 
 // 导出定义在irq.c中的中段门表
 extern void (*interrupt_table[24])(void);
@@ -13,6 +14,8 @@ bool flag_support_x2apic = false;
 uint local_apic_version;
 uint local_apic_max_LVT_entries;
 
+static struct acpi_Multiple_APIC_Description_Table_t *madt;
+
 /**
  * @brief 初始化io_apic
  *
@@ -27,7 +30,28 @@ void apic_io_apic_init()
     io_out8(0x21, 0xff);
     io_out8(0xa1, 0xff);
     kdebug("8259A Masked.");
+    ul madt_addr;
+    kdebug("madt_addr = %#018lx", (ul)madt_addr);
+    acpi_iter_SDT(acpi_get_MADT, &madt_addr);
+    madt = (struct acpi_Multiple_APIC_Description_Table_t *)madt_addr;
+
+    kdebug("MADT->local intr controller addr=%#018lx", madt->Local_Interrupt_Controller_Address);
+    kdebug("MADT->length= %d bytes", madt->header.Length);
 
+    void *ent = (void *)(madt_addr) + sizeof(struct acpi_Multiple_APIC_Description_Table_t);
+    struct apic_Interrupt_Controller_Structure_header_t *header;
+    for (int i = 0; i < 17; ++i)
+    {
+        header = (struct apic_Interrupt_Controller_Structure_header_t *)ent;
+        kdebug("[ %d ] type=%d, length=%d", i, header->type, header->length);
+        if (header->type == 1)
+        {
+            struct acpi_IO_APIC_Structure_t *t = (struct acpi_IO_APIC_Structure_t *)ent;
+            kdebug("IO apic addr = %#018lx", t->IO_APIC_Address);
+        }
+
+        ent += header->length;
+    }
     apic_local_apic_init();
     sti();
 }

+ 12 - 0
kernel/driver/interrupt/apic/apic.h

@@ -4,6 +4,18 @@
 #include"../../../process/ptrace.h"
 #include"../../../exception/irq.h"
 
+struct apic_IO_APIC_map
+{
+    // 间接访问寄存器的物理基地址
+    uint addr_phys;
+    // 索引寄存器虚拟地址
+    unsigned char* virtual_index_addr;
+    // 数据寄存器虚拟地址
+    uint* virtual_data_addr;
+    // EOI寄存器虚拟地址
+    uint* virtual_EOI_addr;
+}apic_ioapic_map;
+
 /**
  * @brief 中断服务程序
  * 

+ 6 - 8
kernel/mm/mm.c

@@ -492,7 +492,7 @@ void init_frame_buffer()
 {
     kinfo("Re-mapping VBE frame buffer...");
     global_CR3 = get_CR3();
-    ul fb_virt_addr = 0xffff800008000000;
+    ul fb_virt_addr = SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + FRAME_BUFFER_MAPPING_OFFSET;
     ul fb_phys_addr = get_VBE_FB_phys_addr();
 
     // 计算帧缓冲区的线性地址对应的pml4页表项的地址
@@ -514,24 +514,23 @@ void init_frame_buffer()
     ul vbe_fb_length = get_VBE_FB_length();
     ul *tmp1;
     // 初始化2M物理页
-    for (ul i = 0; i < (vbe_fb_length<<2); i += PAGE_2M_SIZE)
+    for (ul i = 0; i < (vbe_fb_length << 2); i += PAGE_2M_SIZE)
     {
         // 计算当前2M物理页对应的pdt的页表项的物理地址
         tmp1 = phys_2_virt((ul *)(*tmp & (~0xfffUL)) + (((ul)(fb_virt_addr + i) >> PAGE_2M_SHIFT) & 0x1ff));
 
         // 页面写穿,禁止缓存
-        set_pdt(tmp1, mk_pdt((ul)fb_phys_addr+i, PAGE_KERNEL_PAGE| PAGE_PWT| PAGE_PCD));
+        set_pdt(tmp1, mk_pdt((ul)fb_phys_addr + i, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD));
     }
 
-    set_pos_VBE_FB_addr((uint*)fb_virt_addr);
+    set_pos_VBE_FB_addr((uint *)fb_virt_addr);
     flush_tlb();
     kinfo("VBE frame buffer successfully Re-mapped!");
 }
 
-
 /**
  * @brief 将物理地址映射到页表的函数
- * 
+ *
  * @param virt_addr_start 要映射到的虚拟地址的起始位置
  * @param phys_addr_start 物理地址的起始位置
  * @param length 要映射的区域的长度(字节)
@@ -565,11 +564,10 @@ void mm_map_phys_addr(ul virt_addr_start, ul phys_addr_start, ul length, ul flag
         tmp1 = phys_2_virt((ul *)(*tmp & (~0xfffUL)) + (((ul)(virt_addr_start + i) >> PAGE_2M_SHIFT) & 0x1ff));
 
         // 页面写穿,禁止缓存
-        set_pdt(tmp1, mk_pdt((ul)phys_addr_start+i, flags));
+        set_pdt(tmp1, mk_pdt((ul)phys_addr_start + i, flags));
         ++js;
     }
     kdebug("js=%d", js);
 
-
     flush_tlb();
 }

+ 5 - 0
kernel/mm/mm.h

@@ -35,6 +35,11 @@
 #define Virt_To_2M_Page(kaddr) (memory_management_struct.pages_struct + (virt_2_phys(kaddr) >> PAGE_2M_SHIFT))
 #define Phy_to_2M_Page(kaddr) (memory_management_struct.pages_struct + ((unsigned long)(kaddr) >> PAGE_2M_SHIFT))
 
+// 在这个地址以上的虚拟空间,用来进行特殊的映射
+#define SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE 0xffff800000000000UL
+#define FRAME_BUFFER_MAPPING_OFFSET 0x3000000UL
+#define ACPI_RSDT_MAPPING_OFFSET 0x7000000UL
+#define IO_APIC_MAPPING_OFFSET 0x8000000UL
 // ===== 内存区域属性 =====
 // DMA区域
 #define ZONE_DMA (1 << 0)