M11–M12: IRQ-as-IPC and bus drivers; expand names tree-wide
Two driver-model milestones plus a tree-wide naming pass. Suite 35/35 (QEMU) + host tests green. M11 — IRQ-as-IPC. A ring-3 driver now sleeps until its device interrupts it. New src/kernel/irq.zig: per-GSI endpoint bindings, comptime per-vector trampolines, dispatch = mask GSI -> LAPIC EOI -> notifyLocked, all under one lock region. irq_bind/irq_ack syscalls, gated by the device claim like mmio_map. interruptDispatch no longer EOIs — each handler owns its EOI, because a level line must be masked before it is acknowledged (irq_ack is the unmask). Bindings are keyed on the owning task and released on exit (a shared endpoint's siblings survive). hpetd rewritten interrupt-driven. Tests: hpet (rewritten, reads back the I/O APIC routing) and irqfree. M12 — bus drivers. DeviceDesc gains a parent, making the device table a tree. dev_register (device_register) lets a process publish children below a device it claimed; the kernel enforces resource containment (a child's resources must nest in its parent's), so a descriptor can't fabricate a window over kernel RAM. Descriptor copied in via copyFromUser (physmap walk — an unmapped user pointer fails the call instead of faulting the kernel). Per-parent child cap bounds table exhaustion. sbin/busd.zig is a worked bus driver. Test: bus. Naming — per docs/coding-standards.md: non-acronym abbreviations spelled out (message, descriptor, device_service, scheduler, runtime, physical, interpreter, ...); acronyms kept (IPC, MMIO, DMA, HCD, ...); files are kebab-case (ipc-synchronous.zig, device-service.zig, vfs-protocol.zig, ...). Exceptions: POSIX/C ABI names and Zig idioms (init/len/ptr) kept. Module collisions resolved by specific naming (config -> parameters, device.zig alias -> device_model). AML op/Op disambiguated: op = opcode, Op = operation; per-opcode parse handlers renamed opX -> parseX. New driver docs: drivers.md, driver-model.md (bus/class/HCD shapes + the proposed M13–M16 ABI), coding-standards.md.
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
//! once can't share one fault stack. So the TSS and its IST stack are per-core,
|
||||
//! indexed by CPU number; slot 0 is the BSP.
|
||||
|
||||
const config = @import("config");
|
||||
const parameters = @import("parameters");
|
||||
const gdt = @import("gdt.zig");
|
||||
|
||||
/// x86_64 TSS. `packed` because several 64-bit fields sit at 4-byte-unaligned
|
||||
@@ -37,17 +37,17 @@ const Tss = packed struct {
|
||||
/// The IST slot (1-based, as the IDT gate encodes it) used for critical faults.
|
||||
pub const double_fault_ist = 1;
|
||||
|
||||
const max_cpus = config.max_cpus;
|
||||
pub const ist_stack_size = config.ist_stack_size;
|
||||
const maximum_cpus = parameters.maximum_cpus;
|
||||
pub const ist_stack_size = parameters.ist_stack_size;
|
||||
|
||||
/// One TSS per core (small — kept static). The IST stacks are 16 KiB each, so only
|
||||
/// the **BSP's** is static: it must exist before the frame allocator does, to catch a
|
||||
/// fault during early boot. Each **AP** gets a heap-allocated IST stack at bring-up
|
||||
/// (after the heap is up), the top of which the BSP records here before waking it —
|
||||
/// so we reserve big stacks only for cores that actually come online.
|
||||
var tss_table = [_]Tss{.{}} ** max_cpus;
|
||||
var tss_table = [_]Tss{.{}} ** maximum_cpus;
|
||||
var bsp_ist_stack: [ist_stack_size]u8 align(16) = undefined;
|
||||
var ap_ist_top = [_]usize{0} ** max_cpus; // per-AP IST stack top (0 = BSP / not set)
|
||||
var ap_ist_top = [_]usize{0} ** maximum_cpus; // per-AP IST stack top (0 = BSP / not set)
|
||||
|
||||
/// Loads the task register with the TSS selector. Defined in isr.s.
|
||||
extern fn load_tr(selector: u16) callconv(.c) void;
|
||||
|
||||
Reference in New Issue
Block a user