mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 22:36:48 +00:00
🆕 完成了简单的APIC中断处理功能
This commit is contained in:
parent
9cb628c3b9
commit
ee49849158
@ -47,7 +47,7 @@ void acpi_iter_SDT(bool (*_fun)(const struct acpi_system_description_table_heade
|
|||||||
* @brief 获取MADT信息 Multiple APIC Description Table
|
* @brief 获取MADT信息 Multiple APIC Description Table
|
||||||
*
|
*
|
||||||
* @param _iter_data 要被迭代的信息的结构体
|
* @param _iter_data 要被迭代的信息的结构体
|
||||||
* @param _data 返回信息的结构体指针
|
* @param _data 返回的MADT的虚拟地址
|
||||||
* @param count 返回数组的长度
|
* @param count 返回数组的长度
|
||||||
* @return true
|
* @return true
|
||||||
* @return false
|
* @return false
|
||||||
@ -57,26 +57,9 @@ bool acpi_get_MADT(const struct acpi_system_description_table_header_t *_iter_da
|
|||||||
if (!(_iter_data->Signature[0] == 'A' && _iter_data->Signature[1] == 'P' && _iter_data->Signature[2] == 'I' && _iter_data->Signature[3] == 'C'))
|
if (!(_iter_data->Signature[0] == 'A' && _iter_data->Signature[1] == 'P' && _iter_data->Signature[2] == 'I' && _iter_data->Signature[3] == 'C'))
|
||||||
return false;
|
return false;
|
||||||
//*(struct acpi_Multiple_APIC_Description_Table_t *)_data = *(struct acpi_Multiple_APIC_Description_Table_t *)_iter_data;
|
//*(struct acpi_Multiple_APIC_Description_Table_t *)_data = *(struct acpi_Multiple_APIC_Description_Table_t *)_iter_data;
|
||||||
|
// 返回MADT的虚拟地址
|
||||||
*(ul*)_data = _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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +151,7 @@ void acpi_iter_SDT(bool (*_fun)(const struct acpi_system_description_table_heade
|
|||||||
* @brief 获取MADT信息 Multiple APIC Description Table
|
* @brief 获取MADT信息 Multiple APIC Description Table
|
||||||
*
|
*
|
||||||
* @param _iter_data 要被迭代的信息的结构体
|
* @param _iter_data 要被迭代的信息的结构体
|
||||||
* @param _data 返回信息的结构体指针
|
* @param _data 返回的MADT的虚拟地址
|
||||||
* @param count 返回数组的长度
|
* @param count 返回数组的长度
|
||||||
* @return true
|
* @return true
|
||||||
* @return false
|
* @return false
|
||||||
|
@ -15,21 +15,14 @@ uint local_apic_version;
|
|||||||
uint local_apic_max_LVT_entries;
|
uint local_apic_max_LVT_entries;
|
||||||
|
|
||||||
static struct acpi_Multiple_APIC_Description_Table_t *madt;
|
static struct acpi_Multiple_APIC_Description_Table_t *madt;
|
||||||
|
static struct acpi_IO_APIC_Structure_t *io_apic_ICS;
|
||||||
/**
|
/**
|
||||||
* @brief 初始化io_apic
|
* @brief 初始化io_apic
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void apic_io_apic_init()
|
void apic_io_apic_init()
|
||||||
{
|
{
|
||||||
// 初始化中断门, 中断使用第二个ist
|
|
||||||
for (int i = 32; i <= 55; ++i)
|
|
||||||
set_intr_gate(i, 2, interrupt_table[i - 32]);
|
|
||||||
|
|
||||||
// 屏蔽类8259A芯片
|
|
||||||
io_out8(0x21, 0xff);
|
|
||||||
io_out8(0xa1, 0xff);
|
|
||||||
kdebug("8259A Masked.");
|
|
||||||
ul madt_addr;
|
ul madt_addr;
|
||||||
kdebug("madt_addr = %#018lx", (ul)madt_addr);
|
kdebug("madt_addr = %#018lx", (ul)madt_addr);
|
||||||
acpi_iter_SDT(acpi_get_MADT, &madt_addr);
|
acpi_iter_SDT(acpi_get_MADT, &madt_addr);
|
||||||
@ -38,22 +31,78 @@ void apic_io_apic_init()
|
|||||||
kdebug("MADT->local intr controller addr=%#018lx", madt->Local_Interrupt_Controller_Address);
|
kdebug("MADT->local intr controller addr=%#018lx", madt->Local_Interrupt_Controller_Address);
|
||||||
kdebug("MADT->length= %d bytes", madt->header.Length);
|
kdebug("MADT->length= %d bytes", madt->header.Length);
|
||||||
|
|
||||||
|
// 寻找io apic的ICS
|
||||||
void *ent = (void *)(madt_addr) + sizeof(struct acpi_Multiple_APIC_Description_Table_t);
|
void *ent = (void *)(madt_addr) + sizeof(struct acpi_Multiple_APIC_Description_Table_t);
|
||||||
struct apic_Interrupt_Controller_Structure_header_t *header;
|
struct apic_Interrupt_Controller_Structure_header_t *header = (struct apic_Interrupt_Controller_Structure_header_t *)ent;
|
||||||
for (int i = 0; i < 17; ++i)
|
while (header->length > 2)
|
||||||
{
|
{
|
||||||
header = (struct apic_Interrupt_Controller_Structure_header_t *)ent;
|
header = (struct apic_Interrupt_Controller_Structure_header_t *)ent;
|
||||||
kdebug("[ %d ] type=%d, length=%d", i, header->type, header->length);
|
|
||||||
if (header->type == 1)
|
if (header->type == 1)
|
||||||
{
|
{
|
||||||
struct acpi_IO_APIC_Structure_t *t = (struct acpi_IO_APIC_Structure_t *)ent;
|
struct acpi_IO_APIC_Structure_t *t = (struct acpi_IO_APIC_Structure_t *)ent;
|
||||||
kdebug("IO apic addr = %#018lx", t->IO_APIC_Address);
|
kdebug("IO apic addr = %#018lx", t->IO_APIC_Address);
|
||||||
|
io_apic_ICS = t;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ent += header->length;
|
ent += header->length;
|
||||||
}
|
}
|
||||||
apic_local_apic_init();
|
kdebug("Global_System_Interrupt_Base=%d", io_apic_ICS->Global_System_Interrupt_Base);
|
||||||
sti();
|
|
||||||
|
apic_ioapic_map.addr_phys = io_apic_ICS->IO_APIC_Address;
|
||||||
|
apic_ioapic_map.virtual_index_addr = (unsigned char *)APIC_IO_APIC_VIRT_BASE_ADDR;
|
||||||
|
apic_ioapic_map.virtual_data_addr = (uint *)(APIC_IO_APIC_VIRT_BASE_ADDR + 0x10);
|
||||||
|
apic_ioapic_map.virtual_EOI_addr = (uint *)(APIC_IO_APIC_VIRT_BASE_ADDR + 0x40);
|
||||||
|
|
||||||
|
// 填写页表,完成地址映射
|
||||||
|
mm_map_phys_addr(apic_ioapic_map.virtual_index_addr, apic_ioapic_map.addr_phys, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD);
|
||||||
|
|
||||||
|
// 设置IO APIC ID 为0x0f000000
|
||||||
|
*apic_ioapic_map.virtual_index_addr = 0x00;
|
||||||
|
io_mfence();
|
||||||
|
*apic_ioapic_map.virtual_data_addr = 0x0f000000;
|
||||||
|
io_mfence();
|
||||||
|
|
||||||
|
kdebug("IOAPIC Version:%#010x", ((*apic_ioapic_map.virtual_data_addr) >> 24) & 0xf);
|
||||||
|
io_mfence();
|
||||||
|
|
||||||
|
// 获取IO APIC Version
|
||||||
|
*apic_ioapic_map.virtual_index_addr = 0x01;
|
||||||
|
io_mfence();
|
||||||
|
kdebug("IO APIC Version=%d, Max Redirection Entries=%d", *apic_ioapic_map.virtual_data_addr & 0xff, (((*apic_ioapic_map.virtual_data_addr) >> 16) & 0xff) + 1);
|
||||||
|
|
||||||
|
// 初始化RTE表项,将所有RTE表项屏蔽
|
||||||
|
for (int i = 0x10; i < 0x40; i += 2)
|
||||||
|
{
|
||||||
|
// 以0x20位起始中断向量号,初始化RTE
|
||||||
|
apic_ioapic_write_rte(i, 0x10020 + ((i - 0x10) >> 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开启键盘中断,中断向量号为0x21,物理模式,投递至BSP处理器
|
||||||
|
apic_ioapic_write_rte(0x12, 0x21);
|
||||||
|
// 不需要手动启动IO APIC,只要初始化了RTE寄存器之后,io apic就会自动启用了。
|
||||||
|
// 而且不是每台电脑都有RCBA寄存器,因此不需要手动启用IO APIC
|
||||||
|
/*
|
||||||
|
// get RCBA address
|
||||||
|
io_out32(0xcf8, 0x8000f8f0);
|
||||||
|
uint x = io_in32(0xcfc);
|
||||||
|
uint *p;
|
||||||
|
printk_color(RED, BLACK, "Get RCBA Address:%#010x\n", x);
|
||||||
|
x = x & 0xffffc000UL;
|
||||||
|
printk_color(RED, BLACK, "Get RCBA Address:%#010x\n", x);
|
||||||
|
|
||||||
|
// get OIC address
|
||||||
|
if (x > 0xfec00000 && x < 0xfee00000)
|
||||||
|
{
|
||||||
|
p = (unsigned int *)(x + 0x31feUL+SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// enable IOAPIC
|
||||||
|
x = (*p & 0xffffff00) | 0x100;
|
||||||
|
io_mfence();
|
||||||
|
*p = x;
|
||||||
|
io_mfence();
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -203,6 +252,9 @@ void apic_local_apic_init()
|
|||||||
"rdmsr \n\t"
|
"rdmsr \n\t"
|
||||||
: "=a"(eax), "=d"(edx)::"memory");
|
: "=a"(eax), "=d"(edx)::"memory");
|
||||||
kdebug("LVT_PPR=%#010x", eax);
|
kdebug("LVT_PPR=%#010x", eax);
|
||||||
|
|
||||||
|
// 映射Local APIC 寄存器地址
|
||||||
|
mm_map_phys_addr(APIC_LOCAL_APIC_VIRT_BASE_ADDR, 0xfee00000, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -211,7 +263,23 @@ void apic_local_apic_init()
|
|||||||
*/
|
*/
|
||||||
void apic_init()
|
void apic_init()
|
||||||
{
|
{
|
||||||
|
// 初始化中断门, 中断使用第二个ist
|
||||||
|
for (int i = 32; i <= 55; ++i)
|
||||||
|
set_intr_gate(i, 2, interrupt_table[i - 32]);
|
||||||
|
|
||||||
|
// 屏蔽类8259A芯片
|
||||||
|
io_out8(0x21, 0xff);
|
||||||
|
io_out8(0xa1, 0xff);
|
||||||
|
kdebug("8259A Masked.");
|
||||||
|
|
||||||
|
// enable IMCR
|
||||||
|
io_out8(0x22, 0x70);
|
||||||
|
io_out8(0x23, 0x01);
|
||||||
|
|
||||||
|
apic_local_apic_init();
|
||||||
|
|
||||||
apic_io_apic_init();
|
apic_io_apic_init();
|
||||||
|
sti();
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @brief 中断服务程序
|
* @brief 中断服务程序
|
||||||
@ -221,4 +289,62 @@ void apic_init()
|
|||||||
*/
|
*/
|
||||||
void do_IRQ(struct pt_regs *rsp, ul 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);
|
||||||
|
|
||||||
|
// 向EOI寄存器写入0x00表示结束中断
|
||||||
|
io_mfence();
|
||||||
|
uint *eoi = (uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_EOI);
|
||||||
|
*eoi = 0x00;
|
||||||
|
io_mfence();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 读取RTE寄存器
|
||||||
|
* 由于RTE位宽为64位而IO window寄存器只有32位,因此需要两次读取
|
||||||
|
* @param index 索引值
|
||||||
|
* @return ul
|
||||||
|
*/
|
||||||
|
ul apic_read_ioapic_rte(unsigned char index)
|
||||||
|
{
|
||||||
|
// 由于处理器的乱序执行的问题,需要加入内存屏障以保证结果的正确性。
|
||||||
|
ul ret;
|
||||||
|
// 先读取高32bit
|
||||||
|
*apic_ioapic_map.virtual_index_addr = index + 1;
|
||||||
|
io_mfence();
|
||||||
|
|
||||||
|
ret = *apic_ioapic_map.virtual_data_addr;
|
||||||
|
ret <<= 32;
|
||||||
|
io_mfence();
|
||||||
|
|
||||||
|
// 读取低32bit
|
||||||
|
*apic_ioapic_map.virtual_index_addr = index;
|
||||||
|
io_mfence();
|
||||||
|
ret |= *apic_ioapic_map.virtual_data_addr;
|
||||||
|
io_mfence();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 写入RTE寄存器
|
||||||
|
*
|
||||||
|
* @param index 索引值
|
||||||
|
* @param value 要写入的值
|
||||||
|
*/
|
||||||
|
void apic_ioapic_write_rte(unsigned char index, ul value)
|
||||||
|
{
|
||||||
|
// 先写入低32bit
|
||||||
|
*apic_ioapic_map.virtual_index_addr = index;
|
||||||
|
io_mfence();
|
||||||
|
|
||||||
|
*apic_ioapic_map.virtual_data_addr = value & 0xffffffff;
|
||||||
|
io_mfence();
|
||||||
|
// 再写入高32bit
|
||||||
|
value >>= 32;
|
||||||
|
io_mfence();
|
||||||
|
*apic_ioapic_map.virtual_index_addr = index + 1;
|
||||||
|
io_mfence();
|
||||||
|
*apic_ioapic_map.virtual_data_addr = value & 0xffffffff;
|
||||||
|
io_mfence();
|
||||||
}
|
}
|
@ -3,6 +3,21 @@
|
|||||||
#include "../../../common/asm.h"
|
#include "../../../common/asm.h"
|
||||||
#include"../../../process/ptrace.h"
|
#include"../../../process/ptrace.h"
|
||||||
#include"../../../exception/irq.h"
|
#include"../../../exception/irq.h"
|
||||||
|
#include "../../../mm/mm.h"
|
||||||
|
|
||||||
|
#define APIC_IO_APIC_VIRT_BASE_ADDR SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + IO_APIC_MAPPING_OFFSET
|
||||||
|
#define APIC_LOCAL_APIC_VIRT_BASE_ADDR SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + LOCAL_APIC_MAPPING_OFFSET
|
||||||
|
|
||||||
|
// ======== local apic 寄存器地址偏移量表 =======
|
||||||
|
#define LOCAL_APIC_OFFSET_Local_APIC_ID 0x20
|
||||||
|
#define LOCAL_APIC_OFFSET_Local_APIC_Version 0x30
|
||||||
|
#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
|
||||||
|
|
||||||
struct apic_IO_APIC_map
|
struct apic_IO_APIC_map
|
||||||
{
|
{
|
||||||
@ -24,6 +39,23 @@ struct apic_IO_APIC_map
|
|||||||
*/
|
*/
|
||||||
void do_IRQ(struct pt_regs* rsp, ul number);
|
void do_IRQ(struct pt_regs* rsp, ul number);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 读取RTE寄存器
|
||||||
|
*
|
||||||
|
* @param index 索引值
|
||||||
|
* @return ul
|
||||||
|
*/
|
||||||
|
ul apic_ioapic_read_rte(unsigned char index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 写入RTE寄存器
|
||||||
|
*
|
||||||
|
* @param index 索引值
|
||||||
|
* @param value 要写入的值
|
||||||
|
*/
|
||||||
|
void apic_ioapic_write_rte(unsigned char index, ul value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 初始化apic控制器
|
* @brief 初始化apic控制器
|
||||||
*
|
*
|
||||||
|
@ -557,7 +557,6 @@ void mm_map_phys_addr(ul virt_addr_start, ul phys_addr_start, ul length, ul flag
|
|||||||
|
|
||||||
ul *tmp1;
|
ul *tmp1;
|
||||||
// 初始化2M物理页
|
// 初始化2M物理页
|
||||||
int js = 0;
|
|
||||||
for (ul i = 0; i < (length); i += PAGE_2M_SIZE)
|
for (ul i = 0; i < (length); i += PAGE_2M_SIZE)
|
||||||
{
|
{
|
||||||
// 计算当前2M物理页对应的pdt的页表项的物理地址
|
// 计算当前2M物理页对应的pdt的页表项的物理地址
|
||||||
@ -565,9 +564,7 @@ void mm_map_phys_addr(ul virt_addr_start, ul phys_addr_start, ul length, ul flag
|
|||||||
|
|
||||||
// 页面写穿,禁止缓存
|
// 页面写穿,禁止缓存
|
||||||
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();
|
flush_tlb();
|
||||||
}
|
}
|
@ -39,7 +39,8 @@
|
|||||||
#define SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE 0xffff800000000000UL
|
#define SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE 0xffff800000000000UL
|
||||||
#define FRAME_BUFFER_MAPPING_OFFSET 0x3000000UL
|
#define FRAME_BUFFER_MAPPING_OFFSET 0x3000000UL
|
||||||
#define ACPI_RSDT_MAPPING_OFFSET 0x7000000UL
|
#define ACPI_RSDT_MAPPING_OFFSET 0x7000000UL
|
||||||
#define IO_APIC_MAPPING_OFFSET 0x8000000UL
|
#define IO_APIC_MAPPING_OFFSET 0xfec00000UL
|
||||||
|
#define LOCAL_APIC_MAPPING_OFFSET 0xfee00000UL
|
||||||
// ===== 内存区域属性 =====
|
// ===== 内存区域属性 =====
|
||||||
// DMA区域
|
// DMA区域
|
||||||
#define ZONE_DMA (1 << 0)
|
#define ZONE_DMA (1 << 0)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user