diff --git a/kernel/driver/acpi/acpi.c b/kernel/driver/acpi/acpi.c index 3449a196..416ff436 100644 --- a/kernel/driver/acpi/acpi.c +++ b/kernel/driver/acpi/acpi.c @@ -4,21 +4,25 @@ #include "../multiboot2/multiboot2.h" #include "../../mm/mm.h" -// 获取RSDT entry的虚拟地址 -#define acpi_get_RSDT_entry_vaddr(phys_addr) (ACPI_DESCRIPTION_HEDERS_BASE + (phys_addr)-acpi_RSDT_entry_phys_base) +#define acpi_get_RSDT_entry_vaddr(phys_addr) (ACPI_DESCRIPTION_HEDERS_BASE + (phys_addr)-acpi_RSDT_entry_phys_base) // 获取RSDT entry的虚拟地址 +// #define acpi_get_XSDT_entry_vaddr(phys_addr) (ACPI_DESCRIPTION_HEDERS_BASE + (phys_addr)-acpi_XSDT_entry_phys_base) // 获取XSDT entry的虚拟地址 static struct acpi_RSDP_t *rsdpv1; static struct acpi_RSDP_2_t *rsdpv2; static struct acpi_RSDT_Structure_t *rsdt; +static struct acpi_XSDT_Structure_t *xsdt; static struct multiboot_tag_old_acpi_t old_acpi; static struct multiboot_tag_new_acpi_t new_acpi; static ul acpi_RSDT_offset = 0; +static ul acpi_XSDT_offset = 0; static uint acpi_RSDT_Entry_num = 0; +static uint acpi_XSDT_Entry_num = 0; -// RSDT中的第一个entry所在物理页的基地址 -static ul acpi_RSDT_entry_phys_base = 0; +static ul acpi_RSDT_entry_phys_base = 0; // RSDT中的第一个entry所在物理页的基地址 + +// static ul acpi_XSDT_entry_phys_base = 0; // XSDT中的第一个entry所在物理页的基地址 /** * @brief 迭代器,用于迭代描述符头(位于ACPI标准文件的Table 5-29) @@ -30,17 +34,30 @@ void acpi_iter_SDT(bool (*_fun)(const struct acpi_system_description_table_heade { struct acpi_system_description_table_header_t *sdt_header; - uint *ent = &(rsdt->Entry); - for (int i = 0; i < acpi_RSDT_Entry_num; ++i) + if (acpi_use_xsdt) { + ul *ent = &(xsdt->Entry); + for (int i = 0; i < acpi_XSDT_Entry_num; ++i) + { + mm_map_phys_addr(ACPI_XSDT_DESCRIPTION_HEDERS_BASE + PAGE_2M_SIZE * i, (*(ent + i)) & PAGE_2M_MASK, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); + sdt_header = (struct acpi_system_description_table_header_t *)((ul)(ACPI_XSDT_DESCRIPTION_HEDERS_BASE + PAGE_2M_SIZE * i)); - sdt_header = (struct acpi_system_description_table_header_t *)(acpi_get_RSDT_entry_vaddr((ul)(*(ent + i)))); - kwarn("vvv=%#018lx", (ul)(*(ent + i))); - kwarn("vaddr=%#018lx", (ul)acpi_get_RSDT_entry_vaddr((ul)(*(ent + i)))); - printk_color(ORANGE, BLACK,"kkl=%s\n", sdt_header->Signature); + if (_fun(sdt_header, _data) == true) + return; + } + } + else + { + uint *ent = &(rsdt->Entry); + for (int i = 0; i < acpi_RSDT_Entry_num; ++i) + { - if (_fun(sdt_header, _data) == true) - return; + 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; @@ -61,9 +78,7 @@ bool acpi_get_MADT(const struct acpi_system_description_table_header_t *_iter_da return false; //*(struct acpi_Multiple_APIC_Description_Table_t *)_data = *(struct acpi_Multiple_APIC_Description_Table_t *)_iter_data; // 返回MADT的虚拟地址 - *(ul *)_data = (ul)_iter_data; - printk_color(ORANGE, BLACK,"xxx=%#018lx\n", (ul)_iter_data); return true; } @@ -82,42 +97,105 @@ void acpi_init() int reserved; multiboot2_iter(multiboot2_get_acpi_old_RSDP, &old_acpi, &reserved); - *rsdpv1 = (old_acpi.rsdp); + rsdpv1 = &(old_acpi.rsdp); kdebug("RSDT_phys_Address=%#018lx", rsdpv1->RsdtAddress); kdebug("RSDP_Revision=%d", rsdpv1->Revision); - // 映射RSDT的物理地址到页表 - // 暂定字节数为2MB - // 由于页表映射的原因,需要清除低21位地址,才能填入页表 - ul rsdt_phys_base = rsdpv1->RsdtAddress & PAGE_2M_MASK; - acpi_RSDT_offset = rsdpv1->RsdtAddress - rsdt_phys_base; - mm_map_phys_addr(ACPI_RSDT_VIRT_ADDR_BASE, rsdt_phys_base, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); - kdebug("RSDT mapped!"); - multiboot2_iter(multiboot2_get_acpi_new_RSDP, &new_acpi, &reserved); - *rsdpv2 = new_acpi.rsdp; + rsdpv2 = &(new_acpi.rsdp); + kdebug("Rsdt_v2_phys_Address=%#018lx", rsdpv2->rsdp1.RsdtAddress); + kdebug("Xsdt_phys_Address=%#018lx", rsdpv2->XsdtAddress); kdebug("RSDP_v2_Revision=%d", rsdpv2->rsdp1.Revision); - rsdt = (struct acpi_RSDT_Structure_t *)(ACPI_RSDT_VIRT_ADDR_BASE + acpi_RSDT_offset); + // An ACPI-compatible OS must use the XSDT if present + if (rsdpv2->XsdtAddress != 0x00UL) + { + /* + acpi_use_xsdt = true; + ul xsdt_phys_base = rsdpv2->XsdtAddress & PAGE_2M_MASK; + acpi_XSDT_offset = rsdpv2->XsdtAddress - xsdt_phys_base; + mm_map_phys_addr(ACPI_XSDT_VIRT_ADDR_BASE, xsdt_phys_base, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); + kdebug("XSDT mapped!"); - // 计算RSDT Entry的数量 - kdebug("offset=%d", sizeof(rsdt->header)); - acpi_RSDT_Entry_num = (rsdt->header.Length - 36) / 4; + xsdt = (struct acpi_XSDT_Structure_t *)(ACPI_XSDT_VIRT_ADDR_BASE + acpi_XSDT_offset); + // 计算RSDT Entry的数量 + kdebug("offset=%d", sizeof(xsdt->header)); + kdebug("xsdt sign=%s", xsdt->header.Signature); + acpi_XSDT_Entry_num = (xsdt->header.Length - sizeof(xsdt->header)) / 8; - printk_color(ORANGE, BLACK, "RSDT Length=%dbytes.\n", rsdt->header.Length); - printk_color(ORANGE, BLACK, "RSDT Entry num=%d\n", acpi_RSDT_Entry_num); + printk_color(ORANGE, BLACK, "XSDT Length=%dbytes.\n", xsdt->header.Length); + printk_color(ORANGE, BLACK, "XSDT Entry num=%d\n", acpi_XSDT_Entry_num); - mm_map_phys_addr(ACPI_RSDT_VIRT_ADDR_BASE, rsdt_phys_base, rsdt->header.Length + PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); - // 映射所有的Entry的物理地址 - acpi_RSDT_entry_phys_base = ((ul)(rsdt->Entry)) & PAGE_2M_MASK; - // 由于地址只是32bit的,并且存在脏数据,这里需要手动清除高32bit,否则会触发#GP - acpi_RSDT_entry_phys_base = MASK_HIGH_32bit(acpi_RSDT_entry_phys_base); + mm_map_phys_addr(ACPI_XSDT_VIRT_ADDR_BASE, xsdt_phys_base, xsdt->header.Length + PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); + // 映射所有的Entry的物理地址 + ul *ent = &(xsdt->Entry); + for (int j = 0; j < acpi_XSDT_Entry_num; ++j) + { + kdebug("entry=%#018lx, virt=%#018lx", (*(ent + j)) & PAGE_2M_MASK, ACPI_XSDT_DESCRIPTION_HEDERS_BASE + PAGE_2M_SIZE * j); + // 映射RSDT ENTRY的物理地址 + mm_map_phys_addr(ACPI_XSDT_DESCRIPTION_HEDERS_BASE + PAGE_2M_SIZE * j, (*(ent + j)) & PAGE_2M_MASK, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); + } + */ + // 由于解析XSDT出现问题。暂时只使用Rsdpv2的rsdt,但是这是不符合ACPI规范的!!! + ul rsdt_phys_base = rsdpv2->rsdp1.RsdtAddress & PAGE_2M_MASK; + acpi_RSDT_offset = rsdpv2->rsdp1.RsdtAddress - rsdt_phys_base; + mm_map_phys_addr(ACPI_RSDT_VIRT_ADDR_BASE, rsdt_phys_base, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); + kdebug("RSDT mapped!(v2)"); + 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, "RSDT Length=%dbytes.\n", rsdt->header.Length); + printk_color(ORANGE, BLACK, "RSDT Entry num=%d\n", acpi_RSDT_Entry_num); + + mm_map_phys_addr(ACPI_RSDT_VIRT_ADDR_BASE, rsdt_phys_base, rsdt->header.Length + PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); + // 映射所有的Entry的物理地址 + acpi_RSDT_entry_phys_base = ((ul)(rsdt->Entry)) & PAGE_2M_MASK; + // 由于地址只是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); + } + else if (rsdpv1->RsdtAddress != (uint)0x00UL) + { // 映射RSDT的物理地址到页表 + // 暂定字节数为2MB + // 由于页表映射的原因,需要清除低21位地址,才能填入页表 + ul rsdt_phys_base = rsdpv1->RsdtAddress & PAGE_2M_MASK; + acpi_RSDT_offset = rsdpv1->RsdtAddress - rsdt_phys_base; + mm_map_phys_addr(ACPI_RSDT_VIRT_ADDR_BASE, rsdt_phys_base, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); + kdebug("RSDT mapped!"); + 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, "RSDT Length=%dbytes.\n", rsdt->header.Length); + printk_color(ORANGE, BLACK, "RSDT Entry num=%d\n", acpi_RSDT_Entry_num); + + mm_map_phys_addr(ACPI_RSDT_VIRT_ADDR_BASE, rsdt_phys_base, rsdt->header.Length + PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); + // 映射所有的Entry的物理地址 + acpi_RSDT_entry_phys_base = ((ul)(rsdt->Entry)) & PAGE_2M_MASK; + // 由于地址只是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); + } + else + { + // should not reach here! + kBUG("At acpi_init(): Cannot get right SDT!"); + while (1) + ; + } - 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); kinfo("ACPI module initialized!") } \ No newline at end of file diff --git a/kernel/driver/acpi/acpi.h b/kernel/driver/acpi/acpi.h index d888ab58..3ce7fec6 100644 --- a/kernel/driver/acpi/acpi.h +++ b/kernel/driver/acpi/acpi.h @@ -27,8 +27,11 @@ // 0x80-0xff Reserved for OEM use #define ACPI_RSDT_VIRT_ADDR_BASE SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + ACPI_RSDT_MAPPING_OFFSET +#define ACPI_XSDT_VIRT_ADDR_BASE SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + ACPI_XSDT_MAPPING_OFFSET #define ACPI_DESCRIPTION_HEDERS_BASE ACPI_RSDT_VIRT_ADDR_BASE + (PAGE_2M_SIZE) +#define ACPI_XSDT_DESCRIPTION_HEDERS_BASE ACPI_XSDT_VIRT_ADDR_BASE + (PAGE_2M_SIZE) +bool acpi_use_xsdt = false; struct acpi_RSDP_t { unsigned char Signature[8]; @@ -132,11 +135,11 @@ struct acpi_RSDT_Structure_t struct acpi_XSDT_Structure_t { // 通过RSDT的header->Length可以计算出entry的数量n - // n = (length - 32)/8 + // n = (length - 36)/8 struct acpi_system_description_table_header_t header; // 一个包含了n个64bit物理地址的数组,指向了其他的description headers - ul *Entry; + ul Entry; }; /** diff --git a/kernel/driver/interrupt/apic/apic.c b/kernel/driver/interrupt/apic/apic.c index f2fddc4e..9dc3f1e3 100644 --- a/kernel/driver/interrupt/apic/apic.c +++ b/kernel/driver/interrupt/apic/apic.c @@ -24,8 +24,8 @@ void apic_io_apic_init() { ul madt_addr; - acpi_iter_SDT(acpi_get_MADT, &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); @@ -78,8 +78,7 @@ void apic_io_apic_init() 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 /* @@ -94,7 +93,7 @@ void apic_io_apic_init() // get OIC address if (x > 0xfec00000 && x < 0xfee00000) { - p = (unsigned int *)(x + 0x31feUL+SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE); + p = (unsigned int *)(x + 0x31feUL-apic_ioapic_map.addr_phys+apic_ioapic_map.virtual_index_addr); } // enable IOAPIC @@ -111,6 +110,8 @@ void apic_io_apic_init() */ void apic_local_apic_init() { + // 映射Local APIC 寄存器地址 + mm_map_phys_addr(APIC_LOCAL_APIC_VIRT_BASE_ADDR, 0xfee00000, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); uint a, b, c, d; cpu_cpuid(1, 0, &a, &b, &c, &d); @@ -158,14 +159,25 @@ void apic_local_apic_init() // 检测是否成功启用xAPIC和x2APIC if (eax & 0xc00) kinfo("xAPIC & x2APIC enabled!"); - + /* + io_mfence(); + uint *svr = (uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_SVR); + uint tmp_svr = *svr; + tmp_svr &= (~(1 << 12)); + tmp_svr |= (1 << 8); + kdebug("tmp_svr = %#018lx", tmp_svr); + io_mfence(); + *svr = tmp_svr; + io_mfence(); + kdebug("svr = %#018lx", *svr); + */ // 设置SVR寄存器,开启local APIC、禁止EOI广播 - __asm__ __volatile__("movq 0x80f, %%rcx \n\t" + __asm__ __volatile__("movq $0x80f, %%rcx \n\t" "rdmsr \n\t" "bts $8, %%rax \n\t" "bts $12, %%rax \n\t" - "movq 0x80f, %%rcx \n\t" + "movq $0x80f, %%rcx \n\t" "wrmsr \n\t" "movq $0x80f , %%rcx \n\t" "rdmsr \n\t" @@ -200,6 +212,7 @@ void apic_local_apic_init() : "=a"(eax), "=d"(edx)::"memory"); kdebug("get Local APIC ID: edx=%#010x, eax=%#010x", edx, eax); + kdebug("local_apic_id=%#018lx", *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_ID)); // 获取Local APIC Version // 0x803处是 Local APIC Version register @@ -221,9 +234,9 @@ void apic_local_apic_init() // 由于尚未配置LVT对应的处理程序,因此先屏蔽所有的LVT - __asm__ __volatile__( - "movq $0x82f, %%rcx \n\t" // CMCI - "wrmsr \n\t" + // mask all LVT + __asm__ __volatile__( //"movq $0x82f, %%rcx \n\t" //CMCI + //"wrmsr \n\t" "movq $0x832, %%rcx \n\t" // Timer "wrmsr \n\t" "movq $0x833, %%rcx \n\t" // Thermal Monitor @@ -239,6 +252,25 @@ void apic_local_apic_init() : : "a"(0x10000), "d"(0x00) : "memory"); + + /* + io_mfence(); + *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_CMCI) = 0x1000000; + io_mfence(); + kdebug("cmci = %#018lx", *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_CMCI)); + *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_TIMER) = 0x1000000; + io_mfence(); + *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_THERMAL) = 0x1000000; + io_mfence(); + *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_PERFORMANCE_MONITOR) = 0x1000000; + io_mfence(); + *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_LINT0) = 0x1000000; + io_mfence(); + *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_LINT1) = 0x1000000; + io_mfence(); + *(uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_LVT_ERROR) = 0x1000000; + io_mfence(); + */ kdebug("All LVT Masked"); // 获取TPR寄存器的值 @@ -252,9 +284,6 @@ void apic_local_apic_init() "rdmsr \n\t" : "=a"(eax), "=d"(edx)::"memory"); 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); } /** @@ -289,7 +318,6 @@ void apic_init() */ void do_IRQ(struct pt_regs *rsp, ul number) { - unsigned char x = io_in8(0x60); irq_desc_t *irq = &interrupt_desc[number - 32]; @@ -303,12 +331,16 @@ void do_IRQ(struct pt_regs *rsp, ul number) // 向中断控制器发送应答消息 if (irq->controller != NULL && irq->controller->ack != NULL) irq->controller->ack(number); + else + { - // 向EOI寄存器写入0x00表示结束中断 - io_mfence(); - uint *eoi = (uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_EOI); - *eoi = 0x00; - io_mfence(); + // 向EOI寄存器写入0x00表示结束中断 + __asm__ __volatile__("movq $0x00, %%rdx \n\t" + "movq $0x00, %%rax \n\t" + "movq $0x80b, %%rcx \n\t" + "wrmsr \n\t" :: + : "memory"); + } } /** @@ -395,14 +427,31 @@ void apic_ioapic_uninstall(ul irq_num) void apic_ioapic_level_ack(ul irq_num) // 电平触发 { // 向EOI寄存器写入0x00表示结束中断 + /*io_mfence(); uint *eoi = (uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_EOI); *eoi = 0x00; + io_mfence(); */ + + __asm__ __volatile__("movq $0x00, %%rdx \n\t" + "movq $0x00, %%rax \n\t" + "movq $0x80b, %%rcx \n\t" + "wrmsr \n\t" :: + : "memory"); *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; + /* + uint *eoi = (uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_EOI); + *eoi = 0x00; + + */ + __asm__ __volatile__("movq $0x00, %%rdx \n\t" + "movq $0x00, %%rax \n\t" + "movq $0x80b, %%rcx \n\t" + "wrmsr \n\t" :: + : "memory"); } \ No newline at end of file