ohhhhhhhhhhh (exclude linux-extra-rootfs.img build artifact)
This commit is contained in:
@@ -1 +0,0 @@
|
||||
arch/x86_64/halt.o: arch\x86_64\halt.c
|
||||
Binary file not shown.
@@ -591,6 +591,26 @@ int irq_register(u8 vector, irq_handler_t handler) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Phase7: 显式 EOI(调度器 tick 等"handler 内可能切换任务"的路径用)。
|
||||
* 序列复刻 idt_handler 默认 EOI: 先 LAPIC 钩子再 8259(按向量范围)。
|
||||
* spurious 0xFF 特判与 idt_handler 一致(空 ISR 不该有 EOI)。 */
|
||||
void idt_irq_eoi(u8 vector) {
|
||||
if (vector < 16) vector = (u8)(0x20u + vector);
|
||||
if (vector >= 32 && vector <= 47) {
|
||||
if (g_apic_eoi_hook) g_apic_eoi_hook();
|
||||
if (vector >= 0x28) outb(PIC2_CMD, 0x20);
|
||||
outb(PIC1_CMD, 0x20);
|
||||
} else if (vector >= 48 && vector != 0xFF) {
|
||||
if (g_apic_eoi_hook) g_apic_eoi_hook();
|
||||
}
|
||||
}
|
||||
|
||||
/* Phase8: CPU 异常钩子(DRR 任务级 fault 接管)。 */
|
||||
static int (*g_exc_hook)(u64 vector, u64 err, u64 rip) = 0;
|
||||
void idt_set_exception_hook(int (*hook)(u64 vector, u64 err, u64 rip)) {
|
||||
g_exc_hook = hook;
|
||||
}
|
||||
|
||||
/* Stack frame pushed by isr_common in idt.S */
|
||||
typedef struct {
|
||||
u64 r11, r10, r9, r8, rax, rcx, rdx, rsi, rdi;
|
||||
@@ -601,6 +621,12 @@ typedef struct {
|
||||
|
||||
void idt_handler(isr_frame *frame) {
|
||||
if (frame->vector < 32) {
|
||||
/* Phase8: DRR 异常钩子最前——返回非 0 = 异常已被消费
|
||||
* (fault 任务被杀/切换,控制权不回到日志+停机路径) */
|
||||
if (g_exc_hook &&
|
||||
g_exc_hook(frame->vector, frame->error_code, frame->rip)) {
|
||||
return;
|
||||
}
|
||||
/* CR2: #PF 的 fault 线性地址;CR3: 当前页表基址。
|
||||
* 寄存器 dump 用于定位 fault 指令的操作数来源。 */
|
||||
u64 cr2, cr3;
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
arch/x86_64/idt.o: arch\x86_64\idt.c include\utsm\idt.h \
|
||||
include\utsm\types.h include\utsm\log.h include\utsm\instr.h
|
||||
include\utsm\idt.h:
|
||||
include\utsm\types.h:
|
||||
include\utsm\log.h:
|
||||
include\utsm\instr.h:
|
||||
Binary file not shown.
@@ -1,2 +0,0 @@
|
||||
arch/x86_64/io.o: arch\x86_64\io.c include\utsm\types.h
|
||||
include\utsm\types.h:
|
||||
Binary file not shown.
@@ -0,0 +1,182 @@
|
||||
/* lapic_timer.c — 宿主自持 LAPIC 定时器(调度器 tick 源)
|
||||
*
|
||||
* 为什么不用 PIT 周期中断:默认 FUCK apic_route=1 时 apic.drv 验证完
|
||||
* tick 链路后重新 mask GSI2(PIT IRQ0 线),PIT 周期中断不可达;
|
||||
* LAPIC timer 不经 IOAPIC/PIC 路由,与路由模式解耦,且是 ROADMAP
|
||||
* Phase 2 "LAPIC timer 替代 PIT" 的目标方案。
|
||||
*
|
||||
* 流程:MSR 0x1B → 物理基址 → map_mmio(SAS-R0 直接扩当前 CR3)
|
||||
* → PIT ch0 单发 10ms 采样 CCR 差值校准
|
||||
* → irq_vector_alloc 动态向量 + LVT periodic(先 mask,start 再放开)
|
||||
*/
|
||||
|
||||
#include <utsm/lapic_timer.h>
|
||||
#include <utsm/pit.h>
|
||||
#include <utsm/paging.h>
|
||||
#include <utsm/idt.h>
|
||||
#include <utsm/dkm.h>
|
||||
#include <utsm/log.h>
|
||||
|
||||
extern void outb(u16 port, u8 value);
|
||||
extern u8 inb(u16 port);
|
||||
|
||||
#define MSR_IA32_APIC_BASE 0x1Bu
|
||||
#define APIC_BASE_ENABLE (1ULL << 11)
|
||||
#define APIC_BASE_X2APIC (1ULL << 10)
|
||||
#define LAPIC_DEFAULT_PHYS 0xFEE00000ULL
|
||||
|
||||
#define LAPIC_EOI 0x0B0u
|
||||
#define LAPIC_TPR 0x080u
|
||||
#define LAPIC_SPURIOUS 0x0F0u
|
||||
#define LAPIC_LVT_TIMER 0x320u
|
||||
#define LAPIC_DIV_CONF 0x3E0u
|
||||
#define LAPIC_INIT_CNT 0x380u
|
||||
#define LAPIC_CUR_CNT 0x390u
|
||||
|
||||
#define LVT_MASK (1u << 16)
|
||||
#define LVT_PERIODIC (1u << 17)
|
||||
|
||||
static volatile u32 *g_lapic = 0;
|
||||
static int g_timer_vector = -1;
|
||||
|
||||
static inline u64 rdmsr_(u32 msr) {
|
||||
u32 lo, hi;
|
||||
__asm__ volatile("rdmsr" : "=a"(lo), "=d"(hi) : "c"(msr));
|
||||
return ((u64)hi << 32) | lo;
|
||||
}
|
||||
|
||||
static inline void wrmsr_(u32 msr, u64 v) {
|
||||
u32 lo = (u32)v, hi = (u32)(v >> 32);
|
||||
__asm__ volatile("wrmsr" :: "c"(msr), "a"(lo), "d"(hi));
|
||||
}
|
||||
|
||||
static u32 lapic_read(u32 reg) { return g_lapic[reg / 4]; }
|
||||
static void lapic_write(u32 reg, u32 v) { g_lapic[reg / 4] = v; }
|
||||
|
||||
int lapic_timer_init(u32 freq_hz) {
|
||||
if (freq_hz == 0) freq_hz = 100;
|
||||
|
||||
if (!g_lapic) {
|
||||
u64 base = rdmsr_(MSR_IA32_APIC_BASE);
|
||||
if (!(base & APIC_BASE_ENABLE)) {
|
||||
wrmsr_(MSR_IA32_APIC_BASE, base | APIC_BASE_ENABLE);
|
||||
base = rdmsr_(MSR_IA32_APIC_BASE);
|
||||
}
|
||||
if (base & APIC_BASE_X2APIC) {
|
||||
log_warn("[LAPIC] x2APIC mode, MMIO timer unsupported");
|
||||
return -1;
|
||||
}
|
||||
u64 phys = base & 0xFFFFF000ULL;
|
||||
if (phys == 0) phys = LAPIC_DEFAULT_PHYS;
|
||||
|
||||
const dkm_mmio_api *mm = paging_get_api();
|
||||
if (!mm || !mm->map_mmio) return -2;
|
||||
if (mm->map_mmio(phys, 0x1000) != 0) {
|
||||
log_warn("[LAPIC] map_mmio failed");
|
||||
return -3;
|
||||
}
|
||||
u64 hhdm = 0;
|
||||
const dkm_kernel_api *api = dkm_get_kernel_api();
|
||||
if (api) hhdm = api->hhdm_offset;
|
||||
g_lapic = (volatile u32 *)(hhdm + phys);
|
||||
if (mm->is_mapped && !mm->is_mapped((u64)g_lapic)) {
|
||||
g_lapic = 0;
|
||||
log_warn("[LAPIC] mapped page not reachable");
|
||||
return -4;
|
||||
}
|
||||
|
||||
/* 软件使能(spurious bit8);vector 保留既有值,无则 0xFF */
|
||||
u32 svr = lapic_read(LAPIC_SPURIOUS);
|
||||
if (!(svr & 0x100u)) {
|
||||
u8 vec = (u8)(svr & 0xFFu);
|
||||
if (vec == 0) vec = 0xFFu;
|
||||
lapic_write(LAPIC_SPURIOUS, (u32)vec | 0x100u);
|
||||
}
|
||||
lapic_write(LAPIC_TPR, 0);
|
||||
log_info("[LAPIC] mmio mapped");
|
||||
log_hex64("[LAPIC] phys=", phys);
|
||||
}
|
||||
|
||||
/* ---- PIT 单发校准:divide=16,10ms 窗口采样 CCR 差值 ---- */
|
||||
lapic_write(LAPIC_DIV_CONF, 0x3); /* divide by 16 */
|
||||
lapic_write(LAPIC_LVT_TIMER, (u32)0xFF | LVT_MASK | LVT_PERIODIC); /* 校准期 mask */
|
||||
lapic_write(LAPIC_INIT_CNT, 0xFFFFFFFFu);
|
||||
u32 ccr0 = 0;
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
ccr0 = lapic_read(LAPIC_CUR_CNT);
|
||||
if (ccr0 != 0) break;
|
||||
__asm__ volatile("pause");
|
||||
}
|
||||
|
||||
pit_oneshot_ms(10);
|
||||
u16 prev = pit_latch_count();
|
||||
u32 loops = 0;
|
||||
for (;;) {
|
||||
u16 cur = pit_latch_count();
|
||||
if (cur > prev && loops > 10) break; /* 回绕 = 10ms 到期 */
|
||||
prev = cur;
|
||||
loops++;
|
||||
}
|
||||
u32 ccr1 = lapic_read(LAPIC_CUR_CNT);
|
||||
u64 delta = (u64)ccr0 - (u64)ccr1; /* 16 分频时钟 10ms tick 数 */
|
||||
if (delta < 1000) {
|
||||
log_warn("[LAPIC] timer calibration implausible");
|
||||
lapic_timer_stop();
|
||||
return -5;
|
||||
}
|
||||
|
||||
/* 期望周期 = delta * (1000 / freq_hz) / 10 */
|
||||
u64 init = delta * 1000ULL / (u64)freq_hz / 10ULL;
|
||||
if (init == 0) init = 1;
|
||||
if (init > 0xFFFFFFFFULL) init = 0xFFFFFFFFULL;
|
||||
|
||||
if (g_timer_vector < 0) {
|
||||
int vec = irq_vector_alloc();
|
||||
if (vec < 0) {
|
||||
log_warn("[LAPIC] irq_vector_alloc failed");
|
||||
return -6;
|
||||
}
|
||||
g_timer_vector = vec;
|
||||
}
|
||||
|
||||
/* 按校准值定频编程(LVT 保持 mask,start() 再放开)。
|
||||
* 顺序:divide config → LVT(masked) → initial count。 */
|
||||
lapic_write(LAPIC_DIV_CONF, 0x3);
|
||||
lapic_write(LAPIC_LVT_TIMER,
|
||||
((u32)g_timer_vector & 0xFFu) | LVT_MASK | LVT_PERIODIC);
|
||||
lapic_write(LAPIC_INIT_CNT, (u32)init);
|
||||
|
||||
log_info("[LAPIC] timer calibrated");
|
||||
log_hex64("[LAPIC] ticks/10ms=", delta);
|
||||
log_hex64("[LAPIC] init_count=", init);
|
||||
log_hex64("[LAPIC] vector=", (u64)g_timer_vector);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lapic_timer_vector(void) {
|
||||
return g_timer_vector;
|
||||
}
|
||||
|
||||
void lapic_timer_start(void) {
|
||||
if (!g_lapic || g_timer_vector < 0) return;
|
||||
/* 保持 divide/init 不变,仅解除 mask(periodic 模式已配) */
|
||||
lapic_write(LAPIC_LVT_TIMER,
|
||||
((u32)g_timer_vector & 0xFFu) | LVT_PERIODIC);
|
||||
}
|
||||
|
||||
void lapic_timer_stop(void) {
|
||||
if (g_lapic) {
|
||||
lapic_write(LAPIC_LVT_TIMER, lapic_read(LAPIC_LVT_TIMER) | LVT_MASK);
|
||||
lapic_write(LAPIC_INIT_CNT, 0);
|
||||
}
|
||||
if (g_timer_vector >= 0) {
|
||||
irq_vector_free(g_timer_vector);
|
||||
g_timer_vector = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void lapic_timer_eoi(void) {
|
||||
if (g_lapic) {
|
||||
lapic_write(LAPIC_EOI, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/* pit.c — PIT ch0 单发定时(LAPIC timer 校准用)
|
||||
*
|
||||
* 只用 mode 0(terminal count):单发、无周期中断、不注册 IRQ handler。
|
||||
* 禁用 mode 3 —— B7 定论:PIT mode3 方波经 IOAPIC 边沿路由会双触发 (~200Hz)。
|
||||
*/
|
||||
|
||||
#include <utsm/pit.h>
|
||||
|
||||
extern void outb(u16 port, u8 value);
|
||||
extern u8 inb(u16 port);
|
||||
|
||||
#define PIT_CH0_DATA 0x40
|
||||
#define PIT_CMD 0x43
|
||||
#define PIT_BASE_HZ 1193182ULL
|
||||
|
||||
void pit_oneshot_ms(u32 ms) {
|
||||
u64 div = (PIT_BASE_HZ * (u64)ms) / 1000ULL;
|
||||
if (div == 0) div = 1;
|
||||
if (div > 65535) div = 65535;
|
||||
/* ch0 | lo/hi | mode0 (terminal count) | binary */
|
||||
outb(PIT_CMD, 0x30);
|
||||
outb(PIT_CH0_DATA, (u8)(div & 0xFF));
|
||||
outb(PIT_CH0_DATA, (u8)((div >> 8) & 0xFF));
|
||||
}
|
||||
|
||||
u16 pit_latch_count(void) {
|
||||
outb(PIT_CMD, 0x00); /* ch0 latch 计数(读前锁存) */
|
||||
u16 lo = inb(PIT_CH0_DATA);
|
||||
u16 hi = inb(PIT_CH0_DATA);
|
||||
return (u16)(lo | (hi << 8));
|
||||
}
|
||||
|
||||
int pit_oneshot_expired(void) {
|
||||
u16 c1 = pit_latch_count();
|
||||
u16 c2 = pit_latch_count();
|
||||
/* mode0 计到 0 后回绕继续递减:cur 回升即视为到期 */
|
||||
return c2 >= c1;
|
||||
}
|
||||
|
||||
void pit_quiet(void) {
|
||||
/* ch0 mode0、计数 0:terminal count 立即到期,无后续输出/中断 */
|
||||
outb(PIT_CMD, 0x30);
|
||||
outb(PIT_CH0_DATA, 0x00);
|
||||
outb(PIT_CH0_DATA, 0x00);
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
arch/x86_64/serial.o: arch\x86_64\serial.c include\utsm\types.h
|
||||
include\utsm\types.h:
|
||||
Binary file not shown.
Reference in New Issue
Block a user