예제 #1
0
파일: Global.cs 프로젝트: iSalva/Cosmos
        static public void Init() {
            // See note in Bootstrap about these
            CPU = Bootstrap.CPU;
            PIC = Bootstrap.PIC;

            //TODO: Since this is FCL, its "common". Otherwise it should be
            // system level and not accessible from Core. Need to think about this
            // for the future.
            Console.WriteLine("Finding PCI Devices");
            PCI.Setup();
        }
예제 #2
0
        public static uint MemAlloc(uint aLength)
        {
            if (aLength == 0)
            {
                DebugAndHalt("    Request to retrieve block with size = 0 was halted!");
            }
            var xInterruptsWereEnabled = CPU.DisableInterrupts();

            try
            {
                EnsureIsInitialized();

                var xCurrentTableIdx            = mLastTableIndex;
                DataLookupTable *xCurrentTable  = GlobalSystemInfo.GlobalInformationTable->FirstDataLookupTable;
                DataLookupTable *xPreviousTable = null;
                uint             xResult;
                while (xCurrentTable != null)
                {
                    DebugHex("Scanning DataLookupTable ", xCurrentTableIdx);
                    //DebugHex("At address", (uint)xCurrentTable);
                    if (ScanDataLookupTable(xCurrentTableIdx, xCurrentTable, aLength, out xResult))
                    {
                        DebugHex("Returning handle", xResult);
                        DebugHex("For dataobject size", aLength);
                        if (xResult < CPU.GetEndOfKernel())
                        {
                            DebugAndHalt("Wrong handle returned!");
                        }
                        return(xResult);
                    }
                    xCurrentTableIdx++;
                    xPreviousTable  = xCurrentTable;
                    xCurrentTable   = xCurrentTable->Next;
                    mLastTableIndex = xCurrentTableIdx;
                    mLastEntryIndex = 0;
                }

                // no tables found, lets create a new one, and use that
                if (xPreviousTable == null)
                {
                    // this check should theoretically be unnecessary, but lets keep it, to do some double-checking.
                    DebugAndHalt("No PreviousTable found!");
                }
                Debug("Creating new DataLookupTable");
                var xLastItem         = xPreviousTable->GetEntry(DataLookupTable.EntriesPerTable - 1);
                var xNextTablePointer = (DataLookupTable *)((uint)xLastItem->DataBlock + xLastItem->Size);
                // the memory hasn't been cleared yet, so lets do that now.
                ClearMemory(xNextTablePointer, GlobalSystemInfo.TotalDataLookupTableSize);
                xPreviousTable->Next        = xNextTablePointer;
                xNextTablePointer->Previous = xPreviousTable;

                if (!ScanDataLookupTable(xCurrentTableIdx, xNextTablePointer, aLength, out xResult))
                {
                    // Something seriously weird happened: we could create a new DataLookupTable (with new entries)
                    // but couldn't allocate a new handle from it.
                    DebugAndHalt("    Something seriously weird happened: we could create a new DataLookupTable (with new entries), but couldn't allocate a new handle from it.");
                }
                DebugHex("Returning handle", xResult);
                DebugHex("For dataobject size", aLength);
                mLastTableIndex = xCurrentTableIdx;
                mLastEntryIndex = 0;
                return(xResult);
            }
            finally
            {
                if (xInterruptsWereEnabled)
                {
                    CPU.EnableInterrupts();
                }
                else
                {
                    //Debug("    Not enabling interrupts, because they weren't enabled yet!");
                }
            }
        }
예제 #3
0
 private static void ClearMemory(void *aStartAddress, uint aLength)
 {
     //TODO: Move to memory. Internal access only...
     CPU.ZeroFill((uint)aStartAddress, aLength);
 }
예제 #4
0
파일: RAM.cs 프로젝트: zer09/Cosmos
        public static void Initialize()
        {
            MultiBoot.Header *header = (MultiBoot.Header *)CPU.GetMultiBootInfo();
            MultiBoot.Memory *memory = (MultiBoot.Memory *)header->mmap_address;
            uint memoryEntrySize     = 0;
            uint memoryEntryCount    = 0;

            if (header->mmap_length > 0)
            {
                memoryEntrySize  = memory->size + 4;
                memoryEntryCount = header->mmap_length / memoryEntrySize;
            }
            // if (memoryEntrySize == 0 || memoryEntryCount == 0) throw some kind of kernel error, no memory map
            log.WriteLine("RAM > MMAP Entry: Size=" + memoryEntrySize + ", Count=" + memoryEntryCount);
            ulong endOfKernel = CPU.GetEndOfKernel();

            ulong kernelSize       = 0;
            ulong availableAddress = 0;
            ulong availableSize    = 0;

            MultiBoot.Memory *memoryIterator = memory;
            for (uint memoryEntry = 0; memoryEntry < memoryEntryCount; memoryEntry++, memoryIterator++)
            {
                // Don't need these checks, if we're only grabbing the region the kernel is allocated in for now
                // if (memoryIterator->address + memoryIterator->length <= CONVENTIONAL_MEMORY_SIZE) continue;
                // if (memoryIterator->type != MultiBoot.Memory.TYPE_AVAILABLE) continue;
                if (endOfKernel >= memoryIterator->address)
                {
                    if (endOfKernel <= (memoryIterator->address + memoryIterator->length))
                    {
                        availableAddress  = memoryIterator->address;
                        availableSize     = memoryIterator->length;
                        kernelSize        = endOfKernel - memoryIterator->address;
                        availableAddress += kernelSize;
                        availableSize    -= kernelSize;
                        break;
                    }
                }
            }
            // if (availableSize == 0) throw some kind of kernel error, should not happen... kernel not found in available memory?
            // if (availableSize < PageSize + 1) throw some kind of kernel error, there isn't at least 1 smallest size page (plus tree byte) available after kernel
            log.WriteLine("RAM > MMAP Available: Address=" + ToHex(availableAddress, 64) + ", Length=" + ToHex(availableSize, 64) + ", Kernel=" + ToHex(kernelSize, 64));
            ulong shiftMask = SmallestPageSize;

            log.WriteLine("ShiftMask BeforeLoop: " + shiftMask.ToString());
            byte shiftMaskBit = 0;

            while ((shiftMask & ((ulong)1 << shiftMaskBit)) == 0)
            {
                log.WriteLine("ShiftMask: " + shiftMask.ToString());
                shiftMask |= ((ulong)1 << shiftMaskBit);
                shiftMaskBit++;
            }
            ulong availableShift = availableSize & (~shiftMask);

            log.WriteLine("AvailableShift: " + availableShift.ToString());
            PagesSize = SmallestPageSize;
            while (availableShift != 0)
            {
                availableShift     >>= 1;
                availableShift      &= ~shiftMask;
                TreeSize           <<= 1;
                TreeSize            |= 0x01;
                PagesSize          <<= 1;
                OrderToSmallestPage += 1;
            }
            log.WriteLine("out:" + TreeSize.ToString() + ":" + PagesSize.ToString());
            while ((TreeSize + PagesSize) > availableSize)
            {
                TreeSize  >>= 1;
                PagesSize >>= 1;
                --OrderToSmallestPage;
            }
            log.WriteLine("RAM > Binary Heap: Order=" + ToHex((byte)OrderToSmallestPage, 8) + ", Size=" + ToHex(TreeSize, 64) + ", Paged=" + ToHex(PagesSize, 64));
            TreeData = new byte[TreeSize]; // Replaced by putting directly in memory before paged memory, init to 0's to initialize correctly

            fixed(byte *treePtr = TreeData) Tree = treePtr;

            Pages = Tree + TreeSize;
            // After this point, the allocation tree is ready for use, slightly CPU inefficient initialization is okay, but alloc/dealloc must be fast
            // Code after this needs to be replaced with optimized ASM plugs

            log.WriteLine("RAM> Starts: Tree=" + ToHex((ulong)Tree, 64) + ", Pages=" + ToHex((ulong)Pages, 64));

            // Let's find a page to handle 4000 bytes, should be 1 page, of the smallest size (4096)
            // For testing timing, make sure to remove all console outputs (averages around 100 per second unoptimized)
            int   rtcSec        = Cosmos.Hardware.RTC.Second;
            ulong offset        = 0;
            byte *allocatedPage = null;

            log.WriteLine("RAM> Smallest Page Allocs Per Second: ");
            while (rtcSec == Cosmos.Hardware.RTC.Second)
            {
                ;
            }
            rtcSec = Cosmos.Hardware.RTC.Second;
            log.WriteLine("RAM> Smallest Page Allocs Per Second: ");
            int allocsPerSecond = 0;

            while (rtcSec == Cosmos.Hardware.RTC.Second)
            {
                offset        = 0;
                allocatedPage = RequestPage(1, OrderToSmallestPage, Tree, ref offset);
                offset        = 0;
                ReleasePage(allocatedPage, OrderToSmallestPage, Tree, ref offset);
                allocsPerSecond++;
            }
            log.WriteLine("RAM> Smallest Page Allocs Per Second: " + allocsPerSecond);

            /*
             * ulong offset1 = 0;
             * byte* allocatedPage1 = RequestPage(4000, OrderToSmallestPage, Tree, ref offset1);
             * ulong allocatedPageAddress1 = (ulong)allocatedPage1;
             * Console.WriteLine("Allocated 4000 bytes @ " + ToHex(allocatedPageAddress1, 64));
             *
             * ulong offset2 = 0;
             * byte* allocatedPage2 = RequestPage(6000, OrderToSmallestPage, Tree, ref offset2);
             * ulong allocatedPageAddress2 = (ulong)allocatedPage2;
             * Console.WriteLine("Allocated 6000 bytes @ " + ToHex(allocatedPageAddress2, 64));
             *
             * ulong offset3 = 0;
             * byte* allocatedPage3 = RequestPage(4000, OrderToSmallestPage, Tree, ref offset3);
             * ulong allocatedPageAddress3 = (ulong)allocatedPage3;
             * Console.WriteLine("Allocated 4000 bytes @ " + ToHex(allocatedPageAddress3, 64));
             *
             * offset2 = 0;
             * if (ReleasePage(allocatedPage2, OrderToSmallestPage, Tree, ref offset2)) Console.WriteLine("Released 6000 bytes");
             *
             * offset1 = 0;
             * if (ReleasePage(allocatedPage1, OrderToSmallestPage, Tree, ref offset1)) Console.WriteLine("Released 4000 bytes");
             *
             * offset3 = 0;
             * if (ReleasePage(allocatedPage3, OrderToSmallestPage, Tree, ref offset3)) Console.WriteLine("Released 4000 bytes");
             */
        }