ohhhhhhhhhhh (exclude linux-extra-rootfs.img build artifact)

This commit is contained in:
Linehu
2026-10-01 23:13:42 +08:00
parent 737a2cb0db
commit 1074962546
533 changed files with 133239 additions and 5460 deletions
-1
View File
@@ -1 +0,0 @@
arch/x86_64/halt.o: arch\x86_64\halt.c
Binary file not shown.
+26
View File
@@ -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;
-6
View File
@@ -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.
-2
View File
@@ -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.
+182
View File
@@ -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);
}
}
+45
View File
@@ -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);
}
-2
View File
@@ -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.