XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESystem

【Rust】XFE系统,基于Rust和汇编

公开
关注 0 Fork 0 Star 0
UTF-8
namespace XFESystem.NativeKernel;

public static unsafe class Cpu
{
    public static uint MaximumLeaf, ApicId;
    public static ulong BreakpointCount;
    public static bool BreakpointStackMatches;
    static ulong _expectedAddress, _expectedRip, _resumeRip, _expectedError;
    static bool _faultPending, _faultObserved;

    // IRQ entry must preserve the interrupted System V red zone. Each scheduled
    // thread owns its own IST3 stack, including any suspended interrupt frame.
    // The caller masks interrupts before changing the active thread and this TSS.
    public static bool SetInterruptStack(ulong top)
    {
        byte* tss = (byte*)Native.Storage(2);
        if (tss == null || top == 0 || (top & 15) != 0) return false;
        *(ulong*)(tss + 52) = top;
        Native.MemoryBarrier();
        return true;
    }

    public static bool ProtectionProbe(ulong address, uint kind)
    {
        if (_faultPending || kind > 2) return false;
        _expectedAddress = address;
        _expectedRip = kind == 2 ? address : Native.ProbeInfo(kind * 2);
        _resumeRip = Native.ProbeInfo(kind == 2 ? 4u : kind * 2 + 1);
        _expectedError = kind == 0 ? 0UL : kind == 1 ? 3UL : 17UL;
        _faultObserved = false;
        _faultPending = true;
        Native.ProbeAccess(address, kind);
        bool observed = _faultObserved;
        _faultPending = false;
        return observed;
    }

    public static bool HandleExpectedFault(InterruptFrame* frame, ulong address)
    {
        if (!_faultPending || frame == null || frame->Vector != 14 || frame->Rip != _expectedRip ||
            address != _expectedAddress || (frame->Error & 31) != _expectedError) return false;
        frame->Rip = _resumeRip;
        _faultObserved = true;
        _faultPending = false;
        return true;
    }
    public static bool Initialize()
    {
        uint* result = stackalloc uint[4];
        Native.CpuId(0, 0, result);
        MaximumLeaf = result[0];
        if (MaximumLeaf < 1) return false;
        Native.CpuId(1, 0, result);
        ApicId = CurrentApicId();
        if ((result[3] & (1u << 26)) == 0) return false; // bflat x64 baseline SSE2
        Native.CpuId(0x80000000, 0, result);
        if (result[0] < 0x80000001) return false;
        Native.CpuId(0x80000001, 0, result);
        return (result[3] & (1u << 29)) != 0 && (Native.ReadCr3() & ~4095UL) != 0;
    }

    public static uint CurrentApicId()
    {
        uint* values = stackalloc uint[4];
        Native.CpuId(0, 0, values);
        uint maximum = values[0];
        if (maximum >= 0xb)
        {
            Native.CpuId(0xb, 0, values);
            if (values[1] != 0) return values[3];
        }
        Native.CpuId(1, 0, values);
        return values[1] >> 24;
    }

    public static uint CurrentCoreKey()
    {
        uint* values = stackalloc uint[4];
        Native.CpuId(0, 0, values);
        if (values[0] >= 0xb)
        {
            Native.CpuId(0xb, 0, values);
            if (values[1] != 0 && ((values[2] >> 8) & 255) == 1) return values[3] >> (int)(values[0] & 31);
        }
        return CurrentApicId();
    }

    public static bool InstallWorkerDescriptors(uint cpu)
    {
        ulong* gdt = (ulong*)Native.CpuStorage(0, cpu);
        byte* tss = (byte*)Native.CpuStorage(2, cpu);
        if (gdt == null || tss == null) return false;
        gdt[0] = 0; gdt[1] = 0x00af9a000000ffff; gdt[2] = 0x00cf92000000ffff;
        for (uint i = 0; i < 104; i++) tss[i] = 0;
        *(ulong*)(tss + 36) = (ulong)Native.CpuStorage(3, cpu);
        *(ulong*)(tss + 44) = (ulong)Native.CpuStorage(11, cpu);
        *(ulong*)(tss + 52) = (ulong)Native.CpuStorage(17, cpu);
        *(ushort*)(tss + 102) = 104;
        ulong address = (ulong)tss;
        gdt[3] = 103UL | ((address & 0xffffff) << 16) | (0x89UL << 40) | ((address & 0xff000000) << 32);
        gdt[4] = address >> 32;
        DescriptorPointer gdtr = new DescriptorPointer { Limit = 39, Base = (ulong)gdt };
        DescriptorPointer idtr = new DescriptorPointer { Limit = 4095, Base = (ulong)Native.Storage(1) };
        Native.LoadGdt(&gdtr); Native.LoadTss(24); Native.LoadIdt(&idtr);
        DescriptorPointer actual = new DescriptorPointer();
        Native.ReadGdt(&actual);
        if (actual.Base != gdtr.Base || actual.Limit != gdtr.Limit) return false;
        Native.ReadIdt(&actual);
        return actual.Base == idtr.Base && actual.Limit == idtr.Limit;
    }

    public static bool InstallDescriptors()
    {
        ulong* gdt = (ulong*)Native.Storage(0);
        InterruptGate* idt = (InterruptGate*)Native.Storage(1);
        byte* tss = (byte*)Native.Storage(2);
        if (gdt == null || idt == null || tss == null) return false;
        gdt[0] = 0;
        gdt[1] = 0x00af9a000000ffff;
        gdt[2] = 0x00cf92000000ffff;
        for (uint i = 0; i < 104; i++) tss[i] = 0;
        *(ulong*)(tss + 36) = (ulong)Native.Storage(3); // IST1, private double-fault stack
        *(ulong*)(tss + 44) = (ulong)Native.Storage(11); // IST2, dedicated #DE/#PF recovery stack
        *(ushort*)(tss + 102) = 104; // I/O bitmap absent
        ulong address = (ulong)tss;
        gdt[3] = 103UL | ((address & 0xffffff) << 16) | (0x89UL << 40) | ((address & 0xff000000) << 32);
        gdt[4] = address >> 32;
        DescriptorPointer gdtr = new DescriptorPointer { Limit = 39, Base = (ulong)gdt };
        Native.LoadGdt(&gdtr);
        Native.LoadTss(24);
        for (uint i = 0; i < 256; i++)
        {
            ulong target = Native.IsrAddress(i);
            if (target == 0) return false;
            idt[i].OffsetLow = (ushort)target;
            idt[i].Selector = 8;
            idt[i].Ist = i == 8 ? (byte)1 : i == 0 || i == 14 ? (byte)2 : i >= 32 ? (byte)3 : (byte)0;
            idt[i].Attributes = 0x8e;
            idt[i].OffsetMiddle = (ushort)(target >> 16);
            idt[i].OffsetHigh = (uint)(target >> 32);
            idt[i].Reserved = 0;
        }
        DescriptorPointer idtr = new DescriptorPointer { Limit = 4095, Base = (ulong)idt };
        Native.LoadIdt(&idtr);
        DescriptorPointer actualGdt = new DescriptorPointer(), actualIdt = new DescriptorPointer();
        Native.ReadGdt(&actualGdt);
        Native.ReadIdt(&actualIdt);
        if (actualGdt.Base != gdtr.Base || actualGdt.Limit != gdtr.Limit ||
            actualIdt.Base != idtr.Base || actualIdt.Limit != idtr.Limit) return false;
        ulong prior = BreakpointCount;
        Native.Breakpoint();
        return BreakpointCount == prior + 1 && BreakpointStackMatches;
    }
}