From 3be905f71ea41f50ba175624450057225125a218 Mon Sep 17 00:00:00 2001 From: acevest Date: Thu, 8 Jan 2026 19:30:10 +0800 Subject: [PATCH] =?utf8?q?=E6=95=B4=E7=90=86HPET=E7=9B=B8=E5=85=B3?= =?utf8?q?=E4=BB=A3=E7=A0=81=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- drivers/pci.c | 9 ++ include/apic.h | 3 + include/fixmap.h | 2 + include/hpet.h | 12 +++ include/pci.h | 4 + include/system.h | 2 + kernel/apic.c | 231 ++++------------------------------------------- kernel/hpet.c | 181 +++++++++++++++++++++++++++++++++++++ kernel/setup.c | 16 ++++ kernel/system.c | 19 ++++ 10 files changed, 267 insertions(+), 212 deletions(-) create mode 100644 include/hpet.h create mode 100644 kernel/hpet.c diff --git a/drivers/pci.c b/drivers/pci.c index ad13bf6..c34bc08 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -239,6 +239,15 @@ err: return 0; } +uint32_t pci_get_rcba() { + // Root Complex Base Address寄存器 + + uint32_t cmd = PCI_CMD(0, 31, 0, 0xF0); + uint32_t RCBA = pci_read_config_long(cmd); + + return RCBA; +} + void setup_pci() { if (!probe_pci_bus()) { return; diff --git a/include/apic.h b/include/apic.h index c023249..8a34a17 100644 --- a/include/apic.h +++ b/include/apic.h @@ -187,6 +187,9 @@ union ioapic_rte { typedef union ioapic_rte ioapic_rte_t; +uint64_t ioapic_rte_read(uint32_t index); +void ioapic_rte_write(uint32_t index, uint64_t v); + union hpet_timn_conf_cap { uint64_t value; struct { diff --git a/include/fixmap.h b/include/fixmap.h index 21b5b35..985e325 100644 --- a/include/fixmap.h +++ b/include/fixmap.h @@ -27,6 +27,8 @@ enum { FIX_IO_APIC_BASE, FIX_IO_APIC_END = FIX_IO_APIC_BASE + MAX_IO_APIC_CNT - 1, + FIX_HPET_BASE, + FIX_END_PAD, }; diff --git a/include/hpet.h b/include/hpet.h new file mode 100644 index 0000000..bbe6b00 --- /dev/null +++ b/include/hpet.h @@ -0,0 +1,12 @@ +/* + * ------------------------------------------------------------------------ + * File Name: hpet.h + * Author: Zhao Yanbai + * 2026-01-08 19:28:25 Thursday CST + * Description: none + * ------------------------------------------------------------------------ + */ + +#pragma once + +void hpet_init(); diff --git a/include/pci.h b/include/pci.h index 724c2df..773cac8 100644 --- a/include/pci.h +++ b/include/pci.h @@ -344,3 +344,7 @@ typedef union pci_bridge }; } __attribute__((packed)) pci_bridge_t; #endif + +// 读取RCBA寄存器的值 +// Root Complex Base Address +uint32_t pci_get_rcba(); diff --git a/include/system.h b/include/system.h index 4c5dc1c..a328437 100644 --- a/include/system.h +++ b/include/system.h @@ -265,6 +265,8 @@ extern volatile int reenter; void boot_delay(int ticks); void io_mfence(); + +paddr_t get_rcba_paddr(); #endif #define DISABLE_IDE 1 diff --git a/kernel/apic.c b/kernel/apic.c index c4aa8ac..802f02d 100644 --- a/kernel/apic.c +++ b/kernel/apic.c @@ -247,34 +247,30 @@ void ioapic_rte_write(uint32_t index, uint64_t v) { io_mfence(); } -static uint64_t hpet_ticks = 0; +void ioapic_enable() { + uint32_t rcba_phys_base = (uint32_t)get_rcba_paddr(); -void hpet0_bh_handler() { - // hpet_ticks++; - printlxy(MPL_IRQ, MPO_HPET, "HPET: %lu", hpet_ticks); -} - -void hpet0_irq_handler(unsigned int irq, pt_regs_t* regs, void* dev_id) { - hpet_ticks++; + uint32_t map_offset = 3 * PAGE_SIZE; + vaddr_t rcba_virt_base = (vaddr_t)ioremap(rcba_phys_base + map_offset, 4 * PAGE_SIZE - map_offset); - uint8_t* p = (uint8_t*)0xC00B8002; - *p = *p == ' ' ? 'E' : ' '; + printk("RCBA %08x %08x mapped to %08x\n", rcba_phys_base, rcba_phys_base + map_offset, rcba_virt_base); - add_irq_bh_handler(hpet0_bh_handler, NULL); + // OIC + // 位于RCBA 的 0x31FE 偏移处,是一个16位寄存器 + // bit[7:0]: APIC映射区。决定了IO APIC的间接访问寄存器的地址区间。只有在禁用IO APIC的情况下才能修改。 + // bit[8]: IO APIC使能标志位。 置位使能 复位禁用 + // bit[9] 协处理器错误使能标志位 + // bit[15:10]: 保留 + // + uint16_t* pOIC = (uint16_t*)((uint8_t*)rcba_virt_base + 0x31FE - map_offset); + printk("OIC: %04x\n", *pOIC); + *pOIC = *pOIC | (1 << 8); + printk("OIC: %04x\n", *pOIC); - system.lapic->write(LAPIC_EOI, 0); + iounmap(rcba_virt_base); } void ioapic_init() { - // 先找到RCBA: Root Complex Base Address寄存器 - uint32_t cmd = PCI_CMD(0, 31, 0, 0xF0); - printk("CMD: %08x\n", cmd); - uint32_t RCBA = pci_read_config_long(cmd); - - if ((RCBA & 1) == 0) { - panic("RCBA not enabled\n"); - } - // 把IO APIC映射进地址空间 ioapic_map.phys_base = system.ioapic_addr; ioapic_map.io_reg_sel = (vaddr_t)ioremap(ioapic_map.phys_base, PAGE_SIZE); @@ -308,34 +304,9 @@ void ioapic_init() { ioapic_rte_write(IOAPIC_RTE(i), IOAPIC_RTE_MASK | irq); } - // RCBA - // bit[0]: 使能位 - // bit[13:1]: 保留 - // bit[31:14]: RCBA物理基地址 - // 0x3FFF == (1 << 14) - 1 - uint32_t rcba_phys_base = RCBA & (~0x3FFF); - - printk("RCBA: %08x %08x\n", RCBA, rcba_phys_base); - - // 把RCBA物理基地址映射到内核空间 - uint32_t rcba_page_offset = 3 * PAGE_SIZE; - vaddr_t rcba_virt_base = (vaddr_t)ioremap(rcba_phys_base, 4 * PAGE_SIZE - rcba_page_offset); - printk("RCBA base %08x mapped to %08x\n", rcba_phys_base, rcba_virt_base); - - // OIC - // 位于RCBA 的 0x31FE 偏移处,是一个16位寄存器 - // bit[7:0]: APIC映射区。决定了IO APIC的间接访问寄存器的地址区间。只有在禁用IO APIC的情况下才能修。 - // bit[8]: IO APIC使能标志位。 置位使能 复位禁用 - // bit[9] 协处理器错误使能标志位 - // bit[15:10]: 保留 - // - // 上面得搞成ioremap映射, 因为0x31FE这个超过一页也就是4K了。 - uint16_t* pOIC = (uint16_t*)((uint8_t*)rcba_virt_base + 0x31FE - rcba_page_offset); - printk("OIC: %04x\n", *pOIC); - *pOIC = *pOIC | (1 << 8); - printk("OIC: %04x\n", *pOIC); + uint32_t rcba_phys_base = (uint32_t)get_rcba_paddr(); - iounmap(rcba_virt_base); + ioapic_enable(); uint64_t dst_cpuid = 0; @@ -350,164 +321,6 @@ void ioapic_init() { irq_set_chip(0x00, &ioapic_chip); irq_set_chip(0x01, &ioapic_chip); #endif - - rcba_phys_base = RCBA & (~0x3FFF); - printk("RCBA: %08x %08x\n", RCBA, rcba_phys_base); - rcba_virt_base = (vaddr_t)ioremap(rcba_phys_base, 4 * PAGE_SIZE - rcba_page_offset); - printk("RCBA base %08x mapped to %08x\n", rcba_phys_base, rcba_virt_base); - // HPTC: High Precision Timer Control Register - // bit[1:0] 地址映射范围选择域 - // 取值 地址映射范围 - // 00: 0xFED00000 - 0xFED003FF - // 01: 0xFED01000 - 0xFED013FF - // 10: 0xFED02000 - 0xFED023FF - // 11: 0xFED03000 - 0xFED033FF - // bit[7] 地址映射使能标志位,用于控制HPET设备访问地址的开启与否 - // 只有它置位时芯片组才会将HPET配置寄存器映射到内存空间 - uint32_t* pHPTC = (uint32_t*)((uint8_t*)rcba_virt_base + 0x3404); - printk("HPTC: %08x %08x\n", *pHPTC, pHPTC); - *pHPTC = *pHPTC | (1 << 7) | (0x00); - io_mfence(); - printk("HPTC: %08x\n", *pHPTC); - iounmap(rcba_virt_base); - - vaddr_t hpet_base = (vaddr_t)ioremap(0xFED00000, 0x3FF); - printk("HPET base %08x mapped to %08x\n", 0xFED00000, hpet_base); - - uint64_t GEN_CONF = *(volatile uint64_t*)(hpet_base + 0x10); - printk("GEN_CONF: 0x%08x%08x\n", (uint32_t)(GEN_CONF >> 32), (uint32_t)GEN_CONF); - // // DISABLE HPET - // *(volatile uint64_t*)(hpet_base + 0x10) &= ~(1 << 0); - // io_mfence(); - - // 获取HPET的频率 - uint64_t GCAP_ID = *(volatile uint64_t*)(hpet_base + 0); - // printk("GCAP_ID: %016x\n", GCAP_ID); - printk("GCAP_ID: 0x%08x%08x\n", (uint32_t)(GCAP_ID >> 32), (uint32_t)GCAP_ID); - uint32_t clock_period = (GCAP_ID >> 32); - uint64_t freq_mhz = 1000000000U / clock_period; - printk("HPET clock period: %08x\n", clock_period); - printk("HPET clock %s compatible\n", (GCAP_ID & (1 << 15)) == 0 ? "not" : ""); - printk("HPET clock %s 64-bit capable\n", (GCAP_ID & (1 << 13)) == 0 ? "not" : ""); - printk("HPET clock timer count: %d\n", ((GCAP_ID >> 8) & 0x1F) + 1); - printk("HPET clock frequency: %u MHz\n", freq_mhz); - - GEN_CONF = *(volatile uint64_t*)(hpet_base + 0x10); - printk("GEN_CONF: 0x%08x%08x\n", (uint32_t)(GEN_CONF >> 32), (uint32_t)GEN_CONF); - printk("HPET enabled: %s\n", (GEN_CONF & (1 << 0)) == 0 ? "no" : "yes"); - printk("HPET legacy replacement: %s\n", (GEN_CONF & (1 << 1)) == 0 ? "no" : "yes"); - - uint32_t cpu_irq_vec = 0; - uint32_t ioapic_irq = 23; - - // TIM0_CONF - uint64_t TIM0_CONF = *(volatile uint64_t*)(hpet_base + 0x100); - printk("TIM0_CONF: 0x%08x%08x\n", (uint32_t)(TIM0_CONF >> 32), (uint32_t)TIM0_CONF); - - request_irq(cpu_irq_vec, hpet0_irq_handler, "HPET#0", "HPET#0"); - // HEPT TIM0 连在 IO-APIC的2号引脚上 - // ioapic_rte_write(IOAPIC_RTE(2), 0x20 + 3 | (dst_cpuid << 56)); - -#define TRIGGER_MODE IOAPIC_TRIGGER_MODE_EDGE - ioapic_rte_t rte; - printk("sizeof(ioapic_rte_t): %d\n", sizeof(ioapic_rte_t)); - assert(sizeof(ioapic_rte_t) == 8); - rte.value = 0; - rte.vector = 0x20 + cpu_irq_vec; - rte.delivery_mode = IOAPIC_DELIVERY_MODE_FIXED; - rte.destination_mode = IOAPIC_PHYSICAL_DESTINATION; - rte.trigger_mode = TRIGGER_MODE; - rte.mask = IOAPIC_INT_UNMASKED; - rte.destination = dst_cpuid; - - printk("RTE VALUE %08x", rte.value); - - ioapic_rte_write(IOAPIC_RTE(ioapic_irq), rte.value); - irq_set_chip(cpu_irq_vec, &ioapic_chip); - - // DISABLE HPET - *(volatile uint64_t*)(hpet_base + 0x10) &= ~(1ULL << 0); - io_mfence(); - - hpet_timn_conf_cap_t tim0_conf_cap; - assert(sizeof(tim0_conf_cap) == 8); - tim0_conf_cap.value = TIM0_CONF; - tim0_conf_cap.trigger_mode = TRIGGER_MODE; - tim0_conf_cap.enable_int = 1; // enable - tim0_conf_cap.type = 1; // periodic - tim0_conf_cap.periodic = 0; // readonly - tim0_conf_cap.bit_size = 1; // 0 32bit; 1 64bit - tim0_conf_cap.val_set = 1; - - tim0_conf_cap.counter_bit_size = 0; // 1 32 0 64 - tim0_conf_cap.int_route = ioapic_irq; - tim0_conf_cap.fsb_en = 0; - tim0_conf_cap.fsb_delivery_status = 0; // read only - tim0_conf_cap.reserved0 = 0; - tim0_conf_cap.reserved1 = 0; - tim0_conf_cap.reserved2 = 0; - tim0_conf_cap.int_route_cap = 0; - - TIM0_CONF = tim0_conf_cap.value; - - printk("TIM0_CONF: 0x%08x%08x\n", (uint32_t)(TIM0_CONF >> 32), (uint32_t)TIM0_CONF); - - // uint64_t x = freq_mhz * 1000000ULL; - uint64_t x = freq_mhz * 10000ULL; - *(volatile uint32_t*)(hpet_base + 0x108 + 0x04) = (uint32_t)(x >> 32); - *(volatile uint32_t*)(hpet_base + 0x108 + 0x00) = (uint32_t)(x & 0xFFFFFFFF); - // *(volatile uint64_t*)(hpet_base + 0x108) = x; - io_mfence(); - - *(volatile uint32_t*)(hpet_base + 0x100 + 0x04) = (uint32_t)(TIM0_CONF >> 32); - *(volatile uint32_t*)(hpet_base + 0x100 + 0x00) = (uint32_t)(TIM0_CONF & 0xFFFFFFFF); - // *(volatile uint64_t*)(hpet_base + 0x100) = TIM0_CONF; - io_mfence(); - - // 如果TIMn_CONF的bit6置位(只能在周期模式下置位)的话,这个比较寄存器要写两次 - // 第一次是初始值 - // 第二次是累加值,也就是当MAIN_CNT达到比较寄存器的值时,会自动加上这个 - // 需要说明的是: 第一次要在写TIMn_CONF之前写入 - // 在<>中是这样描述bit6的 - // Software uses this read/write bit only for timers that have been set to periodic mode. - // By writing this bit to a 1, the software is then allowed to directly set a periodic timer's accumulator. - *(volatile uint32_t*)(hpet_base + 0x108 + 0x04) = (uint32_t)(x >> 32); - *(volatile uint32_t*)(hpet_base + 0x108 + 0x00) = (uint32_t)(x & 0xFFFFFFFF); - // *(volatile uint64_t*)(hpet_base + 0x108) = x; - io_mfence(); - - // *(volatile uint32_t*)(hpet_base + 0x108 + 0x04) = (uint32_t)(x >> 32); - // *(volatile uint32_t*)(hpet_base + 0x108 + 0x00) = (uint32_t)(x & 0xFFFFFFFF); - // // *(volatile uint64_t*)(hpet_base + 0x108) = x; - // io_mfence(); - - // MAIN_CNT - *(volatile uint64_t*)(hpet_base + 0xF0) = 0; - // *(volatile uint32_t*)(hpet_base + 0xF0) = 0; - io_mfence(); - - // ENABLE HPET - *(volatile uint64_t*)(hpet_base + 0x10) |= (1ULL << 0); - io_mfence(); - - // // 禁用 Legacy Replacement 模式 - // *(volatile uint64_t*)(hpet_base + 0x10) &= ~(1ULL << 1); - // io_mfence(); - - TIM0_CONF = *(volatile uint64_t*)(hpet_base + 0x100); - - uint32_t ESR = system.lapic->read(LAPIC_ESR); - uint64_t TPR = system.lapic->read(LAPIC_TPR); - uint32_t PPR = system.lapic->read(LAPIC_PPR); - printk("ESR: %08x TPR: %08x PPR: %08x\n", ESR, TPR, PPR); - printk("AFTER TIM0_CONF: 0x%08x%08x\n", (uint32_t)(TIM0_CONF >> 32), (uint32_t)TIM0_CONF); - - // while (1) { - // asm("sti"); - // asm("hlt;"); - // } - // TODO - // iounmap(hpet_base); } void prepare_ap_code(paddr_t paddr) { @@ -625,12 +438,6 @@ void init_apic() { prepare_ap_code(ap_code_addr); wakeup_ap(ap_code_addr); - printk("wait AP ready..."); - extern bool ap_ready(); - while (!ap_ready()) { - asm("pause"); - } - printk("AP ready\n"); } // ## 中断路由路径配置矩阵 diff --git a/kernel/hpet.c b/kernel/hpet.c new file mode 100644 index 0000000..00603a9 --- /dev/null +++ b/kernel/hpet.c @@ -0,0 +1,181 @@ +/* + * ------------------------------------------------------------------------ + * File Name: hpet.c + * Author: Zhao Yanbai + * 2026-01-08 15:59:34 Thursday CST + * Description: none + * ------------------------------------------------------------------------ + */ + +#include +#include +#include +#include +#include +#include + +const static paddr_t hpet_phys_addrs[] = { + 0xFED00000, + 0xFED01000, + 0xFED02000, + 0xFED03000, +}; +const static int hpet_use_phys_addr_index = 0; + +const static int hpet_trigger_mode = IOAPIC_TRIGGER_MODE_EDGE; + +static paddr_t hpet_phys_addr = 0; + +void hpet_hw_enable() { + uint32_t map_offset = 3 * PAGE_SIZE; + vaddr_t rcba_phys_base = (vaddr_t)get_rcba_paddr(); + + vaddr_t rcba_virt_base = (vaddr_t)ioremap(rcba_phys_base + map_offset, 4 * PAGE_SIZE - map_offset); + + printk("RCBA %08x %08x mapped to %08x\n", rcba_phys_base, rcba_phys_base + map_offset, rcba_virt_base); + + // HPTC: High Precision Timer Control Register + // bit[1:0] 地址映射范围选择域 + // 取值 地址映射范围 + // 00: 0xFED00000 - 0xFED003FF + // 01: 0xFED01000 - 0xFED013FF + // 10: 0xFED02000 - 0xFED023FF + // 11: 0xFED03000 - 0xFED033FF + // bit[7] 地址映射使能标志位,用于控制HPET设备访问地址的开启与否 + // 只有它置位时芯片组才会将HPET配置寄存器映射到内存空间 + uint32_t* pHPTC = (uint32_t*)((uint8_t*)rcba_virt_base + 0x3404 - map_offset); + printk("HPTC: %08x %08x\n", *pHPTC, pHPTC); + *pHPTC = *pHPTC | (1 << 7) | (hpet_use_phys_addr_index << 0); + io_mfence(); + printk("HPTC: %08x\n", *pHPTC); + iounmap(rcba_virt_base); +} + +vaddr_t hpet_base() { + return fixid_to_vaddr(FIX_HPET_BASE); +} + +uint64_t hpet_read(uint32_t regoffset) { + return *(uint64_t*)(hpet_base() + regoffset); +} + +uint64_t hpet_write(uint32_t regoffset, uint64_t value) { + *(volatile uint64_t*)(hpet_base() + regoffset) = value; + return value; +} + +#define HPET_REG_CAPABILITY_ID 0x0 +#define HPET_REG_CONFIG 0x10 +#define HPET_REG_INTERRUPT_STATUS 0x20 +#define HPET_REG_MAIN_COUNTER_VALUE 0xF0 +#define HPET_REG_TIMn_CONFIG_CAPABILITY(n) (0x100 + (n) * 0x20) +#define HPET_REG_TIMn_COMPARATOR(n) (0x108 + (n) * 0x20) +#define HPET_REG_TIMn_FSB_INTERRUPT_ROUTE(n) (0x110 + (n) * 0x20) + +void hpet_enable() { + hpet_write(HPET_REG_CONFIG, hpet_read(HPET_REG_CONFIG) | (1ULL << 0)); + io_mfence(); +} + +void hpet_disable() { + hpet_write(HPET_REG_CONFIG, hpet_read(HPET_REG_CONFIG) & ~(1ULL << 0)); + io_mfence(); +} + +uint32_t hpet_clock_period = 0; +uint64_t hpet_clock_mhz_freq = 0; // 32位系统不支持64位除法,所以用MHz为单位 + +static uint64_t hpet_ticks = 0; +void hpet0_bh_handler() { + // hpet_ticks++; + printlxy(MPL_IRQ, MPO_HPET, "HPET: %lu", hpet_ticks); +} +void hpet0_irq_handler(unsigned int irq, pt_regs_t* regs, void* dev_id) { + hpet_ticks++; + + uint8_t* p = (uint8_t*)0xC00B8002; + *p = *p == ' ' ? 'E' : ' '; + + add_irq_bh_handler(hpet0_bh_handler, NULL); + + system.lapic->write(LAPIC_EOI, 0); +} + +extern irq_chip_t ioapic_chip; +void hpet_init() { + assert(hpet_use_phys_addr_index < sizeof(hpet_phys_addrs) / sizeof(hpet_phys_addrs[0])); + hpet_phys_addr = hpet_phys_addrs[hpet_use_phys_addr_index]; + + set_fixmap(FIX_HPET_BASE, hpet_phys_addr); + printk("HPET base %08x mapped to %08x\n", hpet_phys_addr, hpet_base()); + + // + hpet_hw_enable(); + + uint64_t capid = hpet_read(HPET_REG_CAPABILITY_ID); + hpet_clock_period = capid >> 32; + hpet_clock_mhz_freq = 1000000000U / hpet_clock_period; // 32位除法 + printk("HPET Capability and ID: 0x%08x%08x\n", (uint32_t)(capid >> 32), (uint32_t)capid); + printk("HPET legacy replacement route capable: %s\n", (capid & (1ULL << 15)) ? "Y" : "N"); + printk("HPET 64bit capable: %s\n,", (capid & (1ULL << 13)) ? "Y" : "N"); + printk("HPET timer count: %d\n", ((capid >> 8) & 0x1F) + 1); + printk("HPET clock period: %u ns\n", hpet_clock_period); + printk("HPET clock frequency: %u MHz\n", hpet_clock_mhz_freq); + + uint64_t config = hpet_read(HPET_REG_CONFIG); + printk("HPET Configuration: 0x%08x%08x\n", (uint32_t)(config >> 32), (uint32_t)config); + printk("HPET enabled: %s\n", (config & (1ULL << 0)) ? "Y" : "N"); + printk("HPET legacy replacement: %s\n", (config & (1ULL << 1)) ? "Y" : "N"); + + // + hpet_disable(); + + // + uint32_t irq = 0; + uint32_t ioapic_irq = 23; + + // + uint32_t cpu_irq_vec = 0; + request_irq(cpu_irq_vec, hpet0_irq_handler, "HPET#0", "HPET#0"); + + uint64_t dst_cpuid = 0; + ioapic_rte_t rte; + printk("sizeof(ioapic_rte_t): %d\n", sizeof(ioapic_rte_t)); + assert(sizeof(ioapic_rte_t) == 8); + rte.value = 0; + rte.vector = 0x20 + irq; + rte.delivery_mode = IOAPIC_DELIVERY_MODE_FIXED; + rte.destination_mode = IOAPIC_PHYSICAL_DESTINATION; + rte.trigger_mode = hpet_trigger_mode; + rte.mask = IOAPIC_INT_UNMASKED; + rte.destination = dst_cpuid; + + printk("HPET#0 IOAPIC RTE VALUE %08x\n", rte.value); + + ioapic_rte_write(IOAPIC_RTE(ioapic_irq), rte.value); + irq_set_chip(irq, &ioapic_chip); + + uint64_t counter = hpet_clock_mhz_freq * 1000000ULL; + + // 配置HPET#0 + uint64_t tim0_config = 0; + tim0_config |= (hpet_trigger_mode << 1); + tim0_config |= (1 << 2); // enable interrupt + tim0_config |= (1 << 3); // periodic + tim0_config |= (1 << 5); // 64bit + // tim0_config |= (1 << 6); // .... + tim0_config |= (ioapic_irq << 9); // ioapic irq + + printk("TIM0_CONF: 0x%08x%08x\n", (uint32_t)(tim0_config >> 32), (uint32_t)tim0_config); + + hpet_write(HPET_REG_TIMn_CONFIG_CAPABILITY(0), tim0_config); + io_mfence(); + + hpet_write(HPET_REG_TIMn_COMPARATOR(0), counter); + io_mfence(); + + hpet_write(HPET_REG_MAIN_COUNTER_VALUE, 0); + io_mfence(); + + hpet_enable(); +} diff --git a/kernel/setup.c b/kernel/setup.c index 6c2de72..6017144 100644 --- a/kernel/setup.c +++ b/kernel/setup.c @@ -18,6 +18,7 @@ #include #include #include +#include extern void init_mm(); extern void init_buffer(); @@ -74,6 +75,15 @@ void print_kernel_version() { printk(version); } +void wait_ap_boot() { + printk("wait AP ready..."); + extern bool ap_ready(); + while (!ap_ready()) { + asm("pause"); + } + printk("AP ready\n"); +} + void setup_kernel() { printk("sysenter esp mode: fixed to &tss.esp0\n"); @@ -130,6 +140,12 @@ void setup_kernel() { init_apic(); #endif + wait_ap_boot(); + +#if 1 + hpet_init(); +#endif + #if !DISABLE_IDE void ide_init(); ide_init(); diff --git a/kernel/system.c b/kernel/system.c index 2afd1ee..25aad4c 100644 --- a/kernel/system.c +++ b/kernel/system.c @@ -26,6 +26,7 @@ #include #include #include +#include system_t system; tss_t tss; @@ -232,3 +233,21 @@ int sysc_reboot(int mode) { void io_mfence() { asm volatile("mfence" ::: "memory"); } + +paddr_t get_rcba_paddr() { + uint32_t rcba = pci_get_rcba(); + + if ((rcba & 1) == 0) { + panic("RCBA not enabled\n"); + } + + // RCBA + // bit[0]: 使能位 + // bit[13:1]: 保留 + // bit[31:14]: RCBA物理基地址 + // 0x3FFF == (1 << 14) - 1 + + paddr_t rcba_paddr = rcba & (~0x3FFF); + + return rcba_paddr; +} -- 2.47.0