public virtual void Setup(MemoryRegion region, AddressSpaceKind addressSpaceKind) { AddressSpaceKind = addressSpaceKind; region.Size = KMath.FloorToPowerOfTwo(region.Size); _Region = region; var totalPages = region.Size >> BuddyAllocatorImplementation.BUDDY_PAGE_SHIFT; KernelMessage.WriteLine("Init Allocator: StartAddr: {0}, {1} Pages", region.Start, totalPages); // init global memory block // all pages area var pages_size = totalPages * (uint)sizeof(Page); KernelMessage.WriteLine("Page Array Size in bytes: {0}", pages_size); Pages = (Page *)AllocRawMemory(pages_size).Start; KernelMessage.WriteLine("Page Array Addr: {0:X8}", (uint)Pages); var start_addr = region.Start; Zone.free_area = (BuddyAllocatorImplementation.free_area *)AllocRawMemory(BuddyAllocatorImplementation.BUDDY_MAX_ORDER * (uint)sizeof(BuddyAllocatorImplementation.free_area)).Start; fixed(BuddyAllocatorImplementation.mem_zone *zone = &Zone) ZonePtr = zone; BuddyAllocatorImplementation.buddy_system_init( ZonePtr, Pages, start_addr, totalPages); }
public static MemoryRegion AllocateRegion(this IPageFrameAllocator allocator, USize size, AllocatePageOptions options = default) { var pages = KMath.DivCeil(size, 4096); var p = allocator.AllocatePages(pages, options); return(new MemoryRegion(allocator.GetAddress(p), pages * 4096)); }
public MemoryRegion FitToPageCeil() { var start = KMath.AlignValueCeil(Start, 4096); var end = KMath.AlignValueCeil(Start + Size, 4096); return(FromLocation(start, end)); }
private static unsafe int ReadResultDisk(int msgId, byte *buf, uint bufSize) { var lineType = ReadByte(); Assert.True(lineType == (byte)LineType.ResultFile); var msgId_ = ReadInt32(); Assert.True(msgId_ == msgId); var len = ReadInt32(); Assert.True(len <= bufSize); if (len <= 0) { return(0); } var blocks = KMath.DivCeil((uint)len, 512); var tmpBuf = new byte[blocks * 512]; SharedDisk.ReadBlock(0, blocks, tmpBuf); for (var i = 0; i < len; i++) { buf[i] = tmpBuf[i]; } RuntimeMemory.FreeObject(tmpBuf); return(len); }
public static MemoryRegion AllocateRegion(USize size, AllocatePageOptions options = default) { var pages = KMath.DivCeil(size, 4096); var start = AllocatePages(pages, options); return(new MemoryRegion(start, pages * 4096)); }
public void Setup(MemoryRegion region, AddressSpaceKind addrKind) { TraceOptions = new PageFrameAllocatorTraceOptions(); _AddressSpaceKind = addrKind; _Region = region; FistPageNum = region.Start / PageSize; _TotalPages = region.Size / PageSize; kmap = AllocRawMemory(_TotalPages * (uint)sizeof(Page)); PageArray = (Page *)kmap.Start; var firstSelfPageNum = KMath.DivFloor(kmap.Start, 4096); var selfPages = KMath.DivFloor(kmap.Size, 4096); KernelMessage.WriteLine("Page Frame Array allocated {0} pages, beginning with page {1} at {2:X8}", selfPages, firstSelfPageNum, (uint)PageArray); PageTable.KernelTable.SetWritable(kmap.Start, kmap.Size); kmap.Clear(); var addr = FistPageNum * 4096; for (uint i = 0; i < _TotalPages; i++) { //KernelMessage.WriteLine(i); PageArray[i].Address = addr; //if (i != 0) // PageArray[i - 1].Next = &PageArray[i]; addr += 4096; } KernelMessage.WriteLine("Setup free memory"); SetupFreeMemory(); KernelMessage.WriteLine("Build linked lists"); BuildLinkedLists(); KernelMessage.WriteLine("Build linked lists done"); _FreePages = 0; for (uint i = 0; i < _TotalPages; i++) { if (PageArray[i].Status == PageStatus.Free) { _FreePages++; } } //Assert.True(list_head.list_count(FreeList) == _FreePages, "list_head.list_count(FreeList) == _FreePages"); var debugCheckCount = list_head.list_count(FreeList); if (debugCheckCount != _FreePages) { KernelMessage.WriteLine("debugCheckCount {0} != {1}", debugCheckCount, _FreePages); Debug.Break(); } KernelMessage.Path(DebugName, "Pages Free: {0}", FreePages); }
private static uint Cmd_GetPhysicalMemory(SysCallContext *context, SystemMessage *args) { var physAddr = args->Arg1; var pages = KMath.DivCeil(args->Arg2, 4096); KernelMessage.WriteLine("Got Request for {0:X8} pages at Physical Addr {1:X8}", pages, physAddr); var proc = Scheduler.GetCurrentThread().Process; var virtAddr = proc.UserPageAllocator.AllocatePagesAddr(pages); proc.PageTable.Map(virtAddr, physAddr, pages * 4096); return(virtAddr); }
private static uint Cmd_RequestMemory(SysCallContext *context, SystemMessage *args) { var size = args->Arg1; size = KMath.AlignValueCeil(size, 4096); var proc = Scheduler.GetCurrentThread().Process; var map = PhysicalPageManager.AllocateRegion(size); var virtAddr = proc.UserPageAllocator.AllocatePagesAddr(size / 4096); Scheduler.GetCurrentThread().Process.PageTable.Map(virtAddr, map.Start, PhysicalPageManager.GetAllocatorByAddr(map.Start)); return(virtAddr); }
internal static unsafe void SetupAllocator() { Allocator = new RuntimeAllocator(); var ptr = (byte *)SysCalls.RequestMemory(KMath.AlignValueCeil(Allocator.headSize, 4096)); for (var i = 0; i < Allocator.headSize; i++) { *(ptr + i) = 0; // TODO: Optimize } Allocator.List_heads = (malloc_meta **)ptr; AllocatorInitialized = true; }
public static void Setup() { KernelMessage.WriteLine("Multiboot Flags: {0:X}", Multiboot.Flags); BootInfo = (BootInfoHeader *)Address.KernelBootInfo; BootInfo->Magic = lonos.kernel.core.BootInfoHeader.BootInfoMagic; BootInfo->HeapStart = KMath.AlignValueCeil(Address.OriginalKernelElfSection + LoaderStart.OriginalKernelElf.TotalFileSize, 0x1000); BootInfo->HeapSize = 0; BootInfo->InstalledPhysicalMemory = 128 * 1024 * 1024; SetupVideoInfo(); SetupMemoryMap(); }
private static uint Cmd_RequestMessageBuffer(SysCallContext *context, SystemMessage *args) { var size = args->Arg1; var targetProcessID = (int)args->Arg2; var pages = KMath.DivCeil(size, 4096); var currentProc = Scheduler.GetCurrentThread().Process; var tableCurrent = currentProc.PageTable; var targetProc = ProcessManager.System; if (targetProcessID > 0) { targetProc = ProcessManager.GetProcess(targetProcessID); } var tableTarget = targetProc.PageTable; var virtHead = VirtualPageManager.AllocatePages( pages, new AllocatePageOptions { Pool = PageAllocationPool.Global, }); var virtAddr = virtHead; for (var pageIdx = 0; pageIdx < pages; pageIdx++) { var physAddr = PageTable.KernelTable.GetPhysicalAddressFromVirtual(virtAddr); if (tableCurrent != PageTable.KernelTable) { tableCurrent.Map(virtAddr, physAddr, flush: true); } if (tableTarget != PageTable.KernelTable) { tableTarget.Map(virtAddr, physAddr, flush: true); } virtAddr += 4096; } // TODO: implement TargetProcess.RegisterMessageBuffer, because of individual VirtAddr currentProc.GlobalAllocations.Add(new GlobalAllocation { Addr = virtHead, TargetProcID = targetProcessID }); return(virtHead); }
public static void Setup() { KernelMessage.WriteLine("Multiboot Flags: {0:X}", Multiboot.Flags); BootInfo = (BootInfoHeader *)Address.KernelBootInfo; BootInfo->Magic = BootInfoHeader.BootInfoMagic; BootInfo->HeapStart = KMath.AlignValueCeil(Address.OriginalKernelElfSection + LoaderStart.OriginalKernelElf.TotalFileSize, 0x1000); BootInfo->HeapSize = 0; BootInfo->InstalledPhysicalMemory = 256 * 1024 * 1024; BootInfo->PageTableType = KConfig.UsePAE ? PageTableType.PAE : PageTableType.X86; BootInfo->KernelBootStartCycles = PerformanceCounter.KernelBootStartCycles; SetupVideoInfo(); SetupMemoryMap(); }
public unsafe override void SetWritable(uint virtAddr, uint size) { //KernelMessage.WriteLine("Unprotect Memory: Start={0:X}, End={1:X}", virtAddr, virtAddr + size); var pages = KMath.DivCeil(size, 4096); for (var i = 0; i < pages; i++) { var entry = GetTableEntry(virtAddr); entry->Writable = true; virtAddr += 4096; } Flush(); }
public unsafe static void Setup() { kmallocAllocator = new Allocator(); var ptr = (byte *)RawVirtualFrameAllocator.RequestRawVirtalMemoryPages(KMath.AlignValueCeil(Allocator.headSize, 4096)); for (var i = 0; i < Allocator.headSize; i++) { *(ptr + i) = 0; } kmallocAllocator.list_heads = (malloc_meta **)ptr; ManagedMemoy.useAllocator = true; KernelMessage.WriteLine("Memory free: {0} MB", (PageFrameManager.PagesAvailable * 4096) / 1024 / 1024); }
public static unsafe void Setup() { kmallocAllocator = new KernelAllocator(); var ptr = (byte *)VirtualPageManager.AllocatePages(KMath.AlignValueCeil(Allocator.headSize, 4096)); for (var i = 0; i < Allocator.headSize; i++) { *(ptr + i) = 0; } kmallocAllocator.List_heads = (malloc_meta **)ptr; ManagedMemory.UseAllocator = true; KernelMessage.WriteLine("EarlyBootBytesUsed: {0} bytes", ManagedMemory.EarlyBootBytesUsed); KernelMessage.WriteLine("Memory free: {0} MB", PhysicalPageManager.FreePages * 4096 / 1024 / 1024); }
public void Setup(MemoryRegion region, AddressSpaceKind addrKind) { _Requests = 0; _Releases = 0; _AddressSpaceKind = addrKind; _Region = region; FistPageNum = region.Start / PageSize; _TotalPages = region.Size / PageSize; kmap = AllocRawMemory(_TotalPages * (uint)sizeof(Page)); PageArray = (Page *)kmap.Start; NextTryPage = PageArray; var firstSelfPageNum = KMath.DivFloor(kmap.Start, 4096); var selfPages = KMath.DivFloor(kmap.Size, 4096); KernelMessage.WriteLine("Page Frame Array allocated {0} pages, beginning with page {1}", selfPages, firstSelfPageNum); PageTableExtensions.SetWritable(PageTable.KernelTable, kmap.Start, kmap.Size); kmap.Clear(); var addr = FistPageNum * 4096; for (uint i = 0; i < _TotalPages; i++) { PageArray[i].Address = addr; //if (i != 0) // PageArray[i - 1].Next = &PageArray[i]; addr += 4096; } SetupFreeMemory(); _FreePages = 0; for (uint i = 0; i < _TotalPages; i++) { if (PageArray[i].Status == PageStatus.Free) { _FreePages++; } } KernelMessage.WriteLine("Pages Free: {0}", FreePages); }
public async Task BotInfoCommand() { var Data = KMath.CalculateTime(DiscordBot.Instance.UpTime, DateTime.Now); int UserAmount = (await Guild.GetMembersAsync()).Length; var commandCallValue = await DiscordBot.Instance.cacheManger.GetAsync("CommandCall"); var messageCallValue = await DiscordBot.Instance.cacheManger.GetAsync("MessageCall"); var memoryUsage = Process.GetCurrentProcess().PrivateMemorySize64 / 1000 / 1000; EmbedMaker maker = new EmbedMaker(); maker.setTitle("Kururu's info") .addField("Info", $"This bot is running in {await Program.GuildsData.CountAsync()} Servers") .addInlineField("Language", "c#").addInlineField("Owner", "Hedari") .addInlineField("Commands", commandCallValue) .addInlineField("Messages", messageCallValue) .addInlineField("Memory Usage", $"{memoryUsage} MB") .addField("Runtime", $"This bot has been running for, {Data.Days} Day, {Data.Hours} Hour, {Data.Minutes} Minute and {Data.Seconds} Second"); await Channel.SendMessageAsync("", false, maker); }
public static void UnMap(this IPageTable table, Addr virtAddr, USize length, bool flush = false) { if (KConfig.Log.MemoryMapping && length > 4096) { KernelMessage.WriteLine("UnMap: virt={0:X8}, length={2:X8}", virtAddr, length); } var pages = KMath.DivCeil(length, 4096); for (var i = 0; i < pages; i++) { table.MapVirtualAddressToPhysical(virtAddr, 0, false); virtAddr += 4096; } if (flush) { table.Flush(); } }
public unsafe static void InitialKernelProtect_MakeWritable_BySize(uint virtAddr, uint size) { if (!UseKernelWriteProtection) { return; } //KernelMessage.WriteLine("Unprotect Memory: Start={0:X}, End={1:X}", virtAddr, virtAddr + size); var pages = KMath.DivCeil(size, 4096); for (var i = 0; i < pages; i++) { var entry = PageTable.GetTableEntry(virtAddr); entry->Writable = true; virtAddr += 4096; } Native.SetCR3(PageTable.AddrPageDirectory); }
/// <summary> /// Sync specific mappings with another table. /// </summary> public static void MapCopy(this IPageTable table, IPageTable fromTable, Addr virtAddr, USize length, bool present = true, bool flush = false) { if (KConfig.Log.MemoryMapping && length > 4096) { KernelMessage.WriteLine("MapCopy: virt={0:X8}, length={1:X8}", virtAddr, length); } var pages = KMath.DivCeil(length, 4096); for (var i = 0; i < pages; i++) { var physAddr = fromTable.GetPhysicalAddressFromVirtual(virtAddr); table.MapVirtualAddressToPhysical(virtAddr, physAddr, present); virtAddr += 4096; } if (flush) { table.Flush(); } }
private void SetInitialPageStatus(KernelMemoryMapArray *maps, PageStatus status) { for (var i = 0; i < maps->Count; i++) { var map = maps->Items[i]; if (map.Start >= BootInfo.Header->InstalledPhysicalMemory) { continue; } if ((map.AddressSpaceKind & AddressSpaceKind.Physical) == 0) { continue; } var mapPages = KMath.DivCeil(map.Size, 4096); var fistPageNum = KMath.DivFloor(map.Start, 4096); KernelMessage.WriteLine("Mark Pages from {0:X8}, Size {1:X8}, Type {2}, FirstPage {3}, Pages {4}, Status {5}", map.Start, map.Size, (uint)map.Type, (uint)fistPageNum, mapPages, (uint)status); for (var p = fistPageNum; p < fistPageNum + mapPages; p++) { var addr = p * 4096; if (!Region.Contains(addr)) { continue; } if (addr >= BootInfo.Header->InstalledPhysicalMemory) { KernelMessage.WriteLine("addr >= BootInfo.Header->InstalledPhysicalMemory"); break; } var page = GetPageByNum(p); Assert.IsSet(page, "page == null"); page->Status = status; } } }
private static uint RequiredPagesForSize(USize size) { return(KMath.DivCeil(size, 4096)); }
private static unsafe Process CreateProcessFromElf(ElfSections elf, string path, uint argumentBufferSize = 0) { var proc = CreateEmptyProcess(new ProcessCreateOptions() { User = true }); KernelMessage.WriteLine("Create proc: {0}, PID: {1}", path, proc.ProcessID); proc.Path = path; proc.PageTable = PageTable.CreateInstance(); var allocator = new UserInitialPageAllocator() { DebugName = "UserInitial" }; allocator.Setup(new MemoryRegion(500 * 1024 * 1024, 60 * 1024 * 1014), AddressSpaceKind.Virtual); proc.UserPageAllocator = allocator; // Setup User PageTable proc.PageTableAllocAddr = VirtualPageManager.AllocatePages( KMath.DivCeil(proc.PageTable.InitalMemoryAllocationSize, 4096), new AllocatePageOptions { Pool = PageAllocationPool.Identity }); PageTable.KernelTable.SetWritable(proc.PageTableAllocAddr, proc.PageTable.InitalMemoryAllocationSize); proc.PageTable.UserProcSetup(proc.PageTableAllocAddr); proc.PageTable.Map(proc.PageTableAllocAddr, proc.PageTableAllocAddr, proc.PageTable.InitalMemoryAllocationSize); proc.PageTable.MapCopy(PageTable.KernelTable, BootInfoMemoryType.KernelTextSegment); proc.PageTable.SetExecutable(BootInfoMemoryType.KernelTextSegment); proc.PageTable.MapCopy(PageTable.KernelTable, Address.InterruptControlBlock, 4096); proc.PageTable.MapCopy(PageTable.KernelTable, KernelMemoryMapManager.Header->Used.GetMap(BootInfoMemoryType.GDT)); proc.PageTable.MapCopy(PageTable.KernelTable, KernelMemoryMapManager.Header->Used.GetMap(BootInfoMemoryType.IDT)); proc.PageTable.MapCopy(PageTable.KernelTable, KernelMemoryMapManager.Header->Used.GetMap(BootInfoMemoryType.TSS)); var tmpKernelElfHeaders = SetupElfHeader(proc, elf); // Setup ELF Sections for (uint i = 0; i < elf.ProgramHeaderCount; i++) { var section = elf.GetProgramHeader(i); var memSize = section->MemSz; var fileSize = section->FileSz; var virtAddr = section->VAddr; var srcAddr = elf.GetProgramPhysAddr(section); if (memSize == 0) { continue; } KernelMessage.WriteLine("Setup Program Section VAddr {0:X8} SrcAddr {1:X8} Size {2:X8}", virtAddr, srcAddr, memSize); if (virtAddr == Addr.Zero) { var mem = allocator.AllocatePagesAddr(KMath.DivCeil(memSize, 4096)); tmpKernelElfHeaders[i].Addr = mem; virtAddr = mem; } // Map the Sections proc.PageTable.MapCopy(PageTable.KernelTable, srcAddr, virtAddr, memSize); if (i == 0) // TODO: Flags { proc.PageTable.SetReadonly(virtAddr, memSize); } if (memSize > fileSize) { MemoryOperation.Clear(srcAddr + fileSize, memSize - fileSize); } //if (name->Equals(".text")) // proc.PageTable.SetExecutable(virtAddr, size); } KernelMessage.WriteLine("proc sections are ready"); for (uint i = 0; i < elf.SectionHeaderCount; i++) { var section = elf.GetSectionHeader(i); var size = section->Size; var virtAddr = section->Addr; var srcAddr = elf.GetSectionPhysAddr(section); if (size == 0) { continue; } var name = elf.GetSectionName(section); if (virtAddr == Addr.Zero) { } else { if (name->Equals(".bss")) { MemoryOperation.Clear(srcAddr, size); proc.BrkBase = virtAddr + size; KernelMessage.WriteLine("sbrk_base: {0:X8}", proc.BrkBase); } } } // Detect Thread-Main var entryPoint = GetMainEntryPointFromElf(elf); KernelMessage.WriteLine("EntryPoint: {0:X8}", entryPoint); var defaultDispatchEntryPoint = GetDispatchEntryPointFromElf(elf); if (defaultDispatchEntryPoint != Addr.Zero) { KernelMessage.WriteLine("DispatchEntryPoint: {0:X8}", defaultDispatchEntryPoint); proc.Service.Init(defaultDispatchEntryPoint); } var mainThread = Scheduler.CreateThread(proc, new ThreadStartOptions(entryPoint) { ArgumentBufferSize = argumentBufferSize, AllowUserModeIOPort = true, DebugName = "UserProcMainThread", }); KernelMessage.WriteLine("Created Process {0} ProcessID={1}", path, proc.ProcessID); return(proc); }
public static unsafe void Main() { try { ManagedMemoy.InitializeGCMemory(); StartUp.InitializeAssembly(); KMath.Init(); //Mosa.Runtime.StartUp.InitializeRuntimeMetadata(); BootInfo.SetupStage1(); Memory.InitialKernelProtect(); ApiContext.Current = new ApiHost(); Assert.Setup(AssertError); // Setup some pseudo devices DeviceManager.InitStage1(); //Setup Output and Debug devices DeviceManager.InitStage2(); // Write first output KernelMessage.WriteLine("<KERNEL:CONSOLE:BEGIN>"); PerformanceCounter.Setup(BootInfo.Header->KernelBootStartCycles); KernelMessage.WriteLine("Starting Abanu Kernel..."); KernelMessage.WriteLine("KConfig.UseKernelMemoryProtection: {0}", KConfig.UseKernelMemoryProtection); KernelMessage.WriteLine("KConfig.UsePAE: {0}", KConfig.UsePAE); KernelMessage.WriteLine("Apply PageTableType: {0}", (uint)BootInfo.Header->PageTableType); KernelMessage.WriteLine("GCInitialMemory: {0:X8}-{1:X8}", Address.GCInitialMemory, Address.GCInitialMemory + Address.GCInitialMemorySize - 1); Ulongtest1(); Ulongtest2(); InlineTest(); // Detect environment (Memory Maps, Video Mode, etc.) BootInfo.SetupStage2(); KernelMemoryMapManager.Setup(); //KernelMemoryMapManager.Allocate(0x1000 * 1000, BootInfoMemoryType.PageDirectory); // Read own ELF-Headers and Sections KernelElf.Setup(); // Initialize the embedded code (actually only a little proof of concept code) NativeCalls.Setup(); //InitialKernelProtect(); PhysicalPageManager.Setup(); KernelMessage.WriteLine("Phys free: {0}", PhysicalPageManager.FreePages); PhysicalPageManager.AllocatePages(10); KernelMessage.WriteLine("Phys free: {0}", PhysicalPageManager.FreePages); VirtualPageManager.Setup(); Memory.Setup(); // Now Memory Sub System is working. At this point it's valid // to allocate memory dynamically DeviceManager.InitFrameBuffer(); // Setup Programmable Interrupt Table PIC.Setup(); // Setup Interrupt Descriptor Table // Important Note: IDT depends on GDT. Never setup IDT before GDT. IDTManager.Setup(); InitializeUserMode(); SysCallManager.Setup(); KernelMessage.WriteLine("Initialize Runtime Metadata"); StartUp.InitializeRuntimeMetadata(); KernelMessage.WriteLine("Performing some Non-Thread Tests"); Tests(); } catch (Exception ex) { Panic.Error(ex.Message); } if (KConfig.SingleThread) { StartupStage2(); } else { ProcessManager.Setup(StartupStage2); } }
public static unsafe Thread CreateThread(Process proc, ThreadStartOptions options) { Thread thread; uint threadID; lock (SyncRoot) { threadID = FindEmptyThreadSlot(); if (threadID == 0) { ResetTerminatedThreads(); threadID = FindEmptyThreadSlot(); Assert.False(threadID == 0 && Enabled, "No more free Thread-Slots!"); } thread = Threads[threadID]; thread.Status = ThreadStatus.Creating; } // Debug: //options.User = false; thread.User = proc.User; thread.Debug = options.Debug; thread.DebugName = options.DebugName; thread.Priority = options.Priority; var stackSize = options.StackSize; var argBufSize = options.ArgumentBufferSize; thread.ArgumentBufferSize = options.ArgumentBufferSize; var stackPages = KMath.DivCeil(stackSize, PhysicalPageManager.PageSize); if (KConfig.Log.Threads >= KLogLevel.Trace) { KernelMessage.WriteLine("Requesting {0} stack pages", stackPages); } var debugPadding = 8u; stackSize = stackPages * PhysicalPageManager.PageSize; var stack = new Pointer((void *)VirtualPageManager.AllocatePages(stackPages, new AllocatePageOptions { DebugName = "ThreadStack" })); PageTable.KernelTable.SetWritable((uint)stack, stackSize); if (thread.User && proc.PageTable != PageTable.KernelTable) { proc.PageTable.MapCopy(PageTable.KernelTable, (uint)stack, stackSize); } stackSize -= debugPadding; var stackBottom = stack + (int)stackSize; if (KConfig.Log.Threads >= KLogLevel.Trace) { KernelMessage.Write("Create Thread {0}. EntryPoint: {1:X8} Stack: {2:X8}-{3:X8} Type: ", threadID, options.MethodAddr, (uint)stack, (uint)stackBottom - 1); } if (KConfig.Log.Threads >= KLogLevel.Trace) { if (thread.User) { KernelMessage.Write("User"); } else { KernelMessage.Write("Kernel"); } } if (KConfig.Log.Threads >= KLogLevel.Trace) { if (thread.DebugName != null) { KernelMessage.Write(" Thread DebugName: {0}", thread.DebugName); } if (thread.Process != null) { KernelMessage.WriteLine(" Process: {0}", thread.Process.Path); } } // -- kernel stack thread.KernelStackSize = 4 * 4096; //thhread.tssAddr = RawVirtualFrameAllocator.RequestRawVirtalMemoryPages(1); PageTable.KernelTable.SetWritable(KernelStart.TssAddr, 4096); thread.KernelStack = VirtualPageManager.AllocatePages( KMath.DivCeil(thread.KernelStackSize, 4096), new AllocatePageOptions { DebugName = "ThreadKernelStack" }); // TODO: Decrease Kernel Stack, because Stack have to be changed directly because of multi-threading. thread.KernelStackBottom = thread.KernelStack + thread.KernelStackSize; if (KConfig.Log.Threads >= KLogLevel.Trace) { KernelMessage.WriteLine("tssEntry: {0:X8}, tssKernelStack: {1:X8}-{2:X8}", KernelStart.TssAddr, thread.KernelStack, thread.KernelStackBottom - 1); } PageTable.KernelTable.SetWritable(thread.KernelStack, 256 * 4096); // --- uint stackStateOffset = 8; stackStateOffset += argBufSize; uint cS = 0x08; if (thread.User) { cS = 0x1B; } var stateSize = thread.User ? IDTTaskStack.Size : IDTStack.Size; thread.StackTop = (uint)stack; thread.StackBottom = (uint)stackBottom; Intrinsic.Store32(stackBottom, 4, 0xFF00001); // Debug Marker Intrinsic.Store32(stackBottom, 0, 0xFF00002); // Debug Marker Intrinsic.Store32(stackBottom, -4, (uint)stackBottom); Intrinsic.Store32(stackBottom, -(8 + (int)argBufSize), SignalThreadTerminationMethodAddress.ToInt32()); // Address of method that will raise a interrupt signal to terminate thread uint argAddr = (uint)stackBottom - argBufSize; IDTTaskStack *stackState = null; if (thread.User) { stackState = (IDTTaskStack *)VirtualPageManager.AllocatePages(1, new AllocatePageOptions { DebugName = "ThreadStackState" }); if (proc.PageTable != PageTable.KernelTable) { proc.PageTable.MapCopy(PageTable.KernelTable, (uint)stackState, IDTTaskStack.Size); } } else { stackState = (IDTTaskStack *)(stackBottom - 8 - IDTStack.Size); // IDTStackSize is correct - we don't need the Task-Members. } thread.StackState = stackState; if (thread.User && KConfig.Log.Threads >= KLogLevel.Trace) { KernelMessage.WriteLine("StackState at {0:X8}", (uint)stackState); } stackState->Stack.EFLAGS = X86_EFlags.Reserved1; if (thread.User) { // Never set this values for Non-User, otherwise you will override stack informations. stackState->TASK_SS = 0x23; stackState->TASK_ESP = (uint)stackBottom - (uint)stackStateOffset; proc.PageTable.MapCopy(PageTable.KernelTable, thread.KernelStack, thread.KernelStackSize); proc.PageTable.MapCopy(PageTable.KernelTable, KernelStart.TssAddr, 4096); } if (thread.User && options.AllowUserModeIOPort) { byte IOPL = 3; stackState->Stack.EFLAGS = (X86_EFlags)((uint)stackState->Stack.EFLAGS).SetBits(12, 2, IOPL); } stackState->Stack.CS = cS; stackState->Stack.EIP = options.MethodAddr; stackState->Stack.EBP = (uint)(stackBottom - (int)stackStateOffset).ToInt32(); thread.DataSelector = thread.User ? 0x23u : 0x10u; UninterruptableMonitor.Enter(proc.Threads); try { thread.Process = proc; proc.Threads.Add(thread); } finally { UninterruptableMonitor.Exit(proc.Threads); } ThreadsAllocated++; if (ThreadsAllocated > ThreadsMaxAllocated) { ThreadsMaxAllocated = ThreadsAllocated; if (KConfig.Log.Threads >= KLogLevel.Trace) { KernelMessage.WriteLine("Threads Max Allocated: {0}. Allocated {0} Active: {1}", ThreadsMaxAllocated, ThreadsAllocated, GetActiveThreadCount()); } if (KConfig.Log.Threads >= KLogLevel.Trace) { DumpStats(); } } else if (KConfig.Log.Threads >= KLogLevel.Debug) { KernelMessage.WriteLine("Threads Allocated {0} Active: {1}", ThreadsAllocated, GetActiveThreadCount()); } return(thread); }
private static void SetupMemoryMap() { var mbMapCount = Multiboot.MemoryMapCount; BootInfo->MemoryMapArray = (BootInfoMemory *)MallocBootInfoData((USize)(sizeof(MultiBootMemoryMap) * MemoryMapReserve)); for (uint i = 0; i < mbMapCount; i++) { BootInfo->MemoryMapArray[i].Start = Multiboot.GetMemoryMapBase(i); BootInfo->MemoryMapArray[i].Size = Multiboot.GetMemoryMapLength(i); var memType = BootInfoMemoryType.Reserved; var type = (BIOSMemoryMapType)Multiboot.GetMemoryMapType(i); var addressSpaceKind = AddressSpaceKind.Physical; var preMap = false; switch (type) { case BIOSMemoryMapType.Usable: memType = BootInfoMemoryType.SystemUsable; break; case BIOSMemoryMapType.Reserved: memType = BootInfoMemoryType.Reserved; break; case BIOSMemoryMapType.ACPI_Relaimable: memType = BootInfoMemoryType.ACPI_Relaimable; break; case BIOSMemoryMapType.ACPI_NVS_Memory: memType = BootInfoMemoryType.ACPI_NVS_Memory; break; case BIOSMemoryMapType.BadMemory: memType = BootInfoMemoryType.BadMemory; break; default: memType = BootInfoMemoryType.Unknown; break; } BootInfo->MemoryMapArray[i].Type = memType; BootInfo->MemoryMapArray[i].AddressSpaceKind = addressSpaceKind; BootInfo->MemoryMapArray[i].PreMap = preMap; } // It's possible, that the BIOS-Area (@640K) is not correctly setup by Multiboot. So add it here manually to be sure var idx = mbMapCount + 0; BootInfo->MemoryMapArray[idx].Start = 640 * 1024; BootInfo->MemoryMapArray[idx].Size = (1024 - 640) * 1024; BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.CustomReserved; BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Both; //TODO: Physical BootInfo->MemoryMapArray[idx].PreMap = true; idx++; BootInfo->MemoryMapArray[idx].Start = Address.KernelElfSectionPhys; BootInfo->MemoryMapArray[idx].Size = KMath.AlignValueCeil(LoaderStart.OriginalKernelElf.TotalFileSize, 0x1000); BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.KernelElf; BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Physical; BootInfo->MemoryMapArray[idx].PreMap = true; idx++; BootInfo->MemoryMapArray[idx].Start = Address.KernelBootInfo; BootInfo->MemoryMapArray[idx].Size = 0x1000; BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.BootInfoHeader; BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Both; BootInfo->MemoryMapArray[idx].PreMap = true; idx++; BootInfo->MemoryMapArray[idx].Start = BootInfo->HeapStart; BootInfo->MemoryMapArray[idx].Size = 0x1000; //TODO: Recalculate after Setup all Infos BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.BootInfoHeap; BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Both; BootInfo->MemoryMapArray[idx].PreMap = true; idx++; uint stackSize = 0x100000; // 1MB BootInfo->MemoryMapArray[idx].Start = Address.InitialStack - stackSize; BootInfo->MemoryMapArray[idx].Size = stackSize; BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.InitialStack; BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Both; BootInfo->MemoryMapArray[idx].PreMap = true; idx++; BootInfo->MemoryMapArray[idx].Start = Address.GCInitialMemory; BootInfo->MemoryMapArray[idx].Size = Address.GCInitialMemorySize; BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.InitialGCMemory; BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Both; BootInfo->MemoryMapArray[idx].PreMap = true; idx++; BootInfo->MemoryMapArray[idx].Start = LoaderStart.OriginalKernelElf.GetSectionHeader(".bss")->Addr; BootInfo->MemoryMapArray[idx].Size = LoaderStart.OriginalKernelElf.GetSectionHeader(".bss")->Size; BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.KernelBssSegment; BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Virtual; BootInfo->MemoryMapArray[idx].PreMap = false; idx++; BootInfo->MemoryMapArray[idx].Start = LoaderStart.OriginalKernelElf.GetSectionHeader(".text")->Addr; BootInfo->MemoryMapArray[idx].Size = LoaderStart.OriginalKernelElf.GetSectionHeader(".text")->Size; BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.KernelTextSegment; BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Virtual; BootInfo->MemoryMapArray[idx].PreMap = false; idx++; BootInfo->MemoryMapArray[idx].Start = LoaderStart.OriginalKernelElf.GetSectionHeader(".rodata")->Addr; BootInfo->MemoryMapArray[idx].Size = LoaderStart.OriginalKernelElf.GetSectionHeader(".rodata")->Size; BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.KernelROdataSegment; BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Virtual; BootInfo->MemoryMapArray[idx].PreMap = false; idx++; BootInfo->MemoryMapArray[idx].Start = LoaderStart.OriginalKernelElf.GetSectionHeader(".data")->Addr; BootInfo->MemoryMapArray[idx].Size = LoaderStart.OriginalKernelElf.GetSectionHeader(".data")->Size; BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.KernelDataSegment; BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Virtual; BootInfo->MemoryMapArray[idx].PreMap = false; // Avoiding the use of the first megabyte of RAM idx++; BootInfo->MemoryMapArray[idx].Start = 0x0; BootInfo->MemoryMapArray[idx].Size = Address.ReserveMemory; BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.KernelReserved; BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Both; BootInfo->MemoryMapArray[idx].PreMap = false; BootInfo->MemoryMapLength = idx + 1; }
static void SetupMemoryMap() { uint customMaps = 7; var mbMapCount = Multiboot.MemoryMapCount; BootInfo->MemoryMapLength = mbMapCount + customMaps; BootInfo->MemoryMapArray = (BootInfoMemory *)MallocBootInfoData((USize)(sizeof(MultiBootMemoryMap) * MemoryMapReserve)); for (uint i = 0; i < mbMapCount; i++) { BootInfo->MemoryMapArray[i].Start = Multiboot.GetMemoryMapBase(i); BootInfo->MemoryMapArray[i].Size = Multiboot.GetMemoryMapLength(i); var memType = BootInfoMemoryType.Reserved; var type = (BIOSMemoryMapType)Multiboot.GetMemoryMapType(i); switch (type) { case BIOSMemoryMapType.Usable: memType = BootInfoMemoryType.SystemUsable; break; case BIOSMemoryMapType.Reserved: memType = BootInfoMemoryType.Reserved; break; case BIOSMemoryMapType.ACPI_Relaimable: memType = BootInfoMemoryType.ACPI_Relaimable; break; case BIOSMemoryMapType.ACPI_NVS_Memory: memType = BootInfoMemoryType.ACPI_NVS_Memory; break; case BIOSMemoryMapType.BadMemory: memType = BootInfoMemoryType.BadMemory; break; default: memType = BootInfoMemoryType.Unknown; break; } BootInfo->MemoryMapArray[i].Type = memType; } var idx = mbMapCount + 0; BootInfo->MemoryMapArray[idx].Start = Address.OriginalKernelElfSection; BootInfo->MemoryMapArray[idx].Size = KMath.AlignValueCeil(LoaderStart.OriginalKernelElf.TotalFileSize, 0x1000); BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.OriginalKernelElfImage; idx++; BootInfo->MemoryMapArray[idx].Start = Address.KernelElfSection; BootInfo->MemoryMapArray[idx].Size = KMath.AlignValueCeil(LoaderStart.OriginalKernelElf.TotalFileSize, 0x1000); BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.KernelElf; idx++; BootInfo->MemoryMapArray[idx].Start = Address.KernelBootInfo; BootInfo->MemoryMapArray[idx].Size = 0x1000; BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.BootInfoHeader; idx++; BootInfo->MemoryMapArray[idx].Start = BootInfo->HeapStart; BootInfo->MemoryMapArray[idx].Size = 0x1000; //TODO: Recaluclate after Setup all Infos BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.BootInfoHeap; idx++; uint stackSize = 0x100000; // 1MB BootInfo->MemoryMapArray[idx].Start = Address.InitialStack - stackSize; BootInfo->MemoryMapArray[idx].Size = stackSize; BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.InitialStack; idx++; BootInfo->MemoryMapArray[idx].Start = Address.GCInitialMemory; BootInfo->MemoryMapArray[idx].Size = Address.GCInitialMemorySize; BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.InitialGCMemory; idx++; BootInfo->MemoryMapArray[idx].Start = 0x0; BootInfo->MemoryMapArray[idx].Size = 0xA0000; // 640 KB BootInfo->MemoryMapArray[idx].Type = BootInfoMemoryType.KernelReserved; }
private static byte GetOrderForPageCount(uint pages) { return((byte)KMath.Log2OfPowerOf2(KMath.CeilToPowerOfTwo(pages))); }
private static unsafe Process StartProcessFromElf(ElfSections elf, string path, uint argumentBufferSize = 0) { var proc = CreateEmptyProcess(new ProcessCreateOptions() { User = true }); KernelMessage.WriteLine("Create proc: {0}, PID: {1}", path, proc.ProcessID); proc.Path = path; proc.PageTable = PageTable.CreateInstance(); var allocator = new UserInitialPageAllocator() { DebugName = "UserInitial" }; allocator.Setup(new MemoryRegion(500 * 1024 * 1024, 60 * 1024 * 1014), AddressSpaceKind.Virtual); proc.UserPageAllocator = allocator; // Setup User PageTable proc.PageTableAllocAddr = VirtualPageManager.AllocatePages( KMath.DivCeil(proc.PageTable.InitalMemoryAllocationSize, 4096), new AllocatePageOptions { Pool = PageAllocationPool.Identity }); PageTable.KernelTable.SetWritable(proc.PageTableAllocAddr, proc.PageTable.InitalMemoryAllocationSize); proc.PageTable.UserProcSetup(proc.PageTableAllocAddr); proc.PageTable.Map(proc.PageTableAllocAddr, proc.PageTableAllocAddr, proc.PageTable.InitalMemoryAllocationSize); proc.PageTable.MapCopy(PageTable.KernelTable, BootInfoMemoryType.KernelTextSegment); proc.PageTable.SetExecutable(BootInfoMemoryType.KernelTextSegment); proc.PageTable.MapCopy(PageTable.KernelTable, Address.InterruptControlBlock, 4096); proc.PageTable.MapCopy(PageTable.KernelTable, KernelMemoryMapManager.Header->Used.GetMap(BootInfoMemoryType.GDT)); proc.PageTable.MapCopy(PageTable.KernelTable, KernelMemoryMapManager.Header->Used.GetMap(BootInfoMemoryType.IDT)); proc.PageTable.MapCopy(PageTable.KernelTable, KernelMemoryMapManager.Header->Used.GetMap(BootInfoMemoryType.TSS)); var tmpKernelElfHeaders = SetupElfHeader(proc, elf); // Setup ELF Sections for (uint i = 0; i < elf.SectionHeaderCount; i++) { var section = elf.GetSectionHeader(i); var name = elf.GeSectionName(section); var size = section->Size; var virtAddr = section->Addr; var srcAddr = elf.GetSectionPhysAddr(section); if (size == 0) { continue; } if (virtAddr == Addr.Zero) { var mem = allocator.AllocatePagesAddr(KMath.DivCeil(size, 4096)); tmpKernelElfHeaders[i].Addr = mem; virtAddr = mem; } var sb = new StringBuffer(); sb.Append("Map section "); sb.Append(name); sb.Append(" virt={0:X8} src={1:X8} size={2:X8}", virtAddr, srcAddr, size); KernelMessage.WriteLine(sb); //MemoryOperation.Copy4(elf.GetSectionPhysAddr(section), section->Addr, section->Size); // Map the Sections proc.PageTable.MapCopy(PageTable.KernelTable, srcAddr, virtAddr, size); if (name->Equals(".text")) { proc.PageTable.SetExecutable(virtAddr, size); } } KernelMessage.WriteLine("proc sections are ready"); // Detect Thread-Main var entryPoint = GetEntryPointFromElf(elf); KernelMessage.WriteLine("EntryPoint: {0:X8}", entryPoint); var mainThread = Scheduler.CreateThread(proc, new ThreadStartOptions(entryPoint) { ArgumentBufferSize = argumentBufferSize, AllowUserModeIOPort = true, DebugName = "UserProcMainThread", }); KernelMessage.WriteLine("Starting {0} on Thread {1}", path, mainThread.ThreadID); proc.Start(); return(proc); }