diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index 2ab0784..60d8c0e 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -19,28 +19,34 @@ PageDirectoryEntry *pageDirectory; uint32_t isPageTableInUse[0x20]; uint32_t isPageAllocated[0x8000]; + uint32_t isPageConnectedToNext[0x8000]; uint32_t isPageAllocatedCoarse[0x400]; uint32_t pageSearchStart; } PagingInfo; extern void setupMemory(); extern void reservePagesUntilPhysical(uint32_t endPageId); + extern void memset(void *target, uint8_t byte, uint32_t size); -extern void *kernelMapPhysical(void *address); -extern void *kernelMapMultiplePhysicalPages(void *address, uint32_t size); + extern void *findTarFile(void *fileStart, uint32_t fileSize, char *filename); -extern void *mapPageForNewService(PagingInfo *info, void *virtualTarget); -extern void *malloc(uint32_t size); -extern void free(void *address); + +extern void *kernelMapPhysical(void *address); +extern void *kernelMapPhysicalCount(void *address, uint32_t size); extern void *getPage(); -extern void sharePage(PagingInfo *destination, void *sourceAddress, - void *destinationAddress); +extern void *sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress); +extern void freePage(void *pageAddress); +extern void unmapPage(void *pageAddress); + +extern void free(void *address); +extern void *malloc(uint32_t size); extern void *getPhysicalAddressKernel(void *address); extern void *getPhysicalAddress(PageDirectoryEntry *pageDirectory, void *address); extern uint32_t findPage(PagingInfo *info); extern void *mapTemporary(void *address); -extern void *getMultiplePages(uint32_t size); +extern void *getPagesCount(uint32_t size); #endif diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index 2ab0784..60d8c0e 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -19,28 +19,34 @@ PageDirectoryEntry *pageDirectory; uint32_t isPageTableInUse[0x20]; uint32_t isPageAllocated[0x8000]; + uint32_t isPageConnectedToNext[0x8000]; uint32_t isPageAllocatedCoarse[0x400]; uint32_t pageSearchStart; } PagingInfo; extern void setupMemory(); extern void reservePagesUntilPhysical(uint32_t endPageId); + extern void memset(void *target, uint8_t byte, uint32_t size); -extern void *kernelMapPhysical(void *address); -extern void *kernelMapMultiplePhysicalPages(void *address, uint32_t size); + extern void *findTarFile(void *fileStart, uint32_t fileSize, char *filename); -extern void *mapPageForNewService(PagingInfo *info, void *virtualTarget); -extern void *malloc(uint32_t size); -extern void free(void *address); + +extern void *kernelMapPhysical(void *address); +extern void *kernelMapPhysicalCount(void *address, uint32_t size); extern void *getPage(); -extern void sharePage(PagingInfo *destination, void *sourceAddress, - void *destinationAddress); +extern void *sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress); +extern void freePage(void *pageAddress); +extern void unmapPage(void *pageAddress); + +extern void free(void *address); +extern void *malloc(uint32_t size); extern void *getPhysicalAddressKernel(void *address); extern void *getPhysicalAddress(PageDirectoryEntry *pageDirectory, void *address); extern uint32_t findPage(PagingInfo *info); extern void *mapTemporary(void *address); -extern void *getMultiplePages(uint32_t size); +extern void *getPagesCount(uint32_t size); #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 33b9b77..f8b6f03 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -37,7 +37,7 @@ } void loadAndScheduleLoader(void *multibootInfo) { - void *address = kernelMapMultiplePhysicalPages(multibootInfo, 4); + void *address = kernelMapPhysicalCount(multibootInfo, 4); initrd = findInitrd(address, &initrdSize); loadInitrdProgram("loader", NULL); } diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index 2ab0784..60d8c0e 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -19,28 +19,34 @@ PageDirectoryEntry *pageDirectory; uint32_t isPageTableInUse[0x20]; uint32_t isPageAllocated[0x8000]; + uint32_t isPageConnectedToNext[0x8000]; uint32_t isPageAllocatedCoarse[0x400]; uint32_t pageSearchStart; } PagingInfo; extern void setupMemory(); extern void reservePagesUntilPhysical(uint32_t endPageId); + extern void memset(void *target, uint8_t byte, uint32_t size); -extern void *kernelMapPhysical(void *address); -extern void *kernelMapMultiplePhysicalPages(void *address, uint32_t size); + extern void *findTarFile(void *fileStart, uint32_t fileSize, char *filename); -extern void *mapPageForNewService(PagingInfo *info, void *virtualTarget); -extern void *malloc(uint32_t size); -extern void free(void *address); + +extern void *kernelMapPhysical(void *address); +extern void *kernelMapPhysicalCount(void *address, uint32_t size); extern void *getPage(); -extern void sharePage(PagingInfo *destination, void *sourceAddress, - void *destinationAddress); +extern void *sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress); +extern void freePage(void *pageAddress); +extern void unmapPage(void *pageAddress); + +extern void free(void *address); +extern void *malloc(uint32_t size); extern void *getPhysicalAddressKernel(void *address); extern void *getPhysicalAddress(PageDirectoryEntry *pageDirectory, void *address); extern uint32_t findPage(PagingInfo *info); extern void *mapTemporary(void *address); -extern void *getMultiplePages(uint32_t size); +extern void *getPagesCount(uint32_t size); #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 33b9b77..f8b6f03 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -37,7 +37,7 @@ } void loadAndScheduleLoader(void *multibootInfo) { - void *address = kernelMapMultiplePhysicalPages(multibootInfo, 4); + void *address = kernelMapPhysicalCount(multibootInfo, 4); initrd = findInitrd(address, &initrdSize); loadInitrdProgram("loader", NULL); } diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c index c6aa5f9..1c63546 100644 --- a/src/kernel/memory/malloc.c +++ b/src/kernel/memory/malloc.c @@ -23,7 +23,7 @@ void *malloc(uint32_t size) { uint32_t sizeBit = LOG2(size) + 1; if (sizeBit > 10) { - return getMultiplePages(((size - 1) >> 12) + 1); + return getPagesCount(((size - 1) >> 12) + 1); } AllocationBlock *block = allocationData[sizeBit], *last = 0; while (1) { @@ -60,7 +60,7 @@ void free(void *location) { AllocationBlock *block = (void *)((uintptr_t)location & ~0xFFF); if (block->magic != ALLOCATION_MAGIC) { - // freePage(location); + freePage(location); return; } uint16_t index = (uint16_t)((uintptr_t)location & 0xFFF) / block->blockSize; diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index 2ab0784..60d8c0e 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -19,28 +19,34 @@ PageDirectoryEntry *pageDirectory; uint32_t isPageTableInUse[0x20]; uint32_t isPageAllocated[0x8000]; + uint32_t isPageConnectedToNext[0x8000]; uint32_t isPageAllocatedCoarse[0x400]; uint32_t pageSearchStart; } PagingInfo; extern void setupMemory(); extern void reservePagesUntilPhysical(uint32_t endPageId); + extern void memset(void *target, uint8_t byte, uint32_t size); -extern void *kernelMapPhysical(void *address); -extern void *kernelMapMultiplePhysicalPages(void *address, uint32_t size); + extern void *findTarFile(void *fileStart, uint32_t fileSize, char *filename); -extern void *mapPageForNewService(PagingInfo *info, void *virtualTarget); -extern void *malloc(uint32_t size); -extern void free(void *address); + +extern void *kernelMapPhysical(void *address); +extern void *kernelMapPhysicalCount(void *address, uint32_t size); extern void *getPage(); -extern void sharePage(PagingInfo *destination, void *sourceAddress, - void *destinationAddress); +extern void *sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress); +extern void freePage(void *pageAddress); +extern void unmapPage(void *pageAddress); + +extern void free(void *address); +extern void *malloc(uint32_t size); extern void *getPhysicalAddressKernel(void *address); extern void *getPhysicalAddress(PageDirectoryEntry *pageDirectory, void *address); extern uint32_t findPage(PagingInfo *info); extern void *mapTemporary(void *address); -extern void *getMultiplePages(uint32_t size); +extern void *getPagesCount(uint32_t size); #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 33b9b77..f8b6f03 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -37,7 +37,7 @@ } void loadAndScheduleLoader(void *multibootInfo) { - void *address = kernelMapMultiplePhysicalPages(multibootInfo, 4); + void *address = kernelMapPhysicalCount(multibootInfo, 4); initrd = findInitrd(address, &initrdSize); loadInitrdProgram("loader", NULL); } diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c index c6aa5f9..1c63546 100644 --- a/src/kernel/memory/malloc.c +++ b/src/kernel/memory/malloc.c @@ -23,7 +23,7 @@ void *malloc(uint32_t size) { uint32_t sizeBit = LOG2(size) + 1; if (sizeBit > 10) { - return getMultiplePages(((size - 1) >> 12) + 1); + return getPagesCount(((size - 1) >> 12) + 1); } AllocationBlock *block = allocationData[sizeBit], *last = 0; while (1) { @@ -60,7 +60,7 @@ void free(void *location) { AllocationBlock *block = (void *)((uintptr_t)location & ~0xFFF); if (block->magic != ALLOCATION_MAGIC) { - // freePage(location); + freePage(location); return; } uint16_t index = (uint16_t)((uintptr_t)location & 0xFFF) / block->blockSize; diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index 9e528bd..9dca1f3 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -2,6 +2,10 @@ #include #include +#define ADDRESS(pageId) PTR((pageId) << 12) +#define PAGE_ID(address) (U32(address) >> 12) +#define PAGE_OFFSET(address) (U32(address) & 0xFFF) + PageTableEntry *kernelCodePageTable, *kernelDataPageTable; PagingInfo *kernelPhysicalPages, *kernelVirtualPages; @@ -29,18 +33,18 @@ } void *mapTemporary(void *physical) { - kernelDataPageTable[3].targetAddress = U32(physical) >> 12; + kernelDataPageTable[3].targetAddress = PAGE_ID(physical); kernelDataPageTable[3].writable = 1; kernelDataPageTable[3].present = 1; invalidatePage(0xFF803); - return temporaryPage + (U32(physical) & 0xFFF); + return temporaryPage + PAGE_OFFSET(physical); } void *getPhysicalAddress(PageDirectoryEntry *pageDirectory, void *address) { VirtualAddress *virtual = (void *)&address; uint32_t pageTableId = pageDirectory[virtual->pageDirectoryIndex].pageTableID; - PageTableEntry *pageTable = mapTemporary(PTR(pageTableId << 12)); + PageTableEntry *pageTable = mapTemporary(ADDRESS(pageTableId)); uint32_t pageBase = pageTable[virtual->pageTableIndex].targetAddress; return PTR(pageBase << 12 | virtual->pageOffset); } @@ -49,6 +53,21 @@ return getPhysicalAddress(kernelVirtualPages->pageDirectory, address); } +void reservePage(PagingInfo *info, uint32_t pageId) { + uint32_t coarsePosition = pageId / 32; + info->isPageAllocated[coarsePosition] |= 1 << (pageId % 32); + if (info->isPageAllocated[coarsePosition] == ~0) { + info->isPageAllocatedCoarse[coarsePosition / 32] |= + 1 << (coarsePosition % 32); + } +} + +void reservePagesCount(PagingInfo *info, uint32_t startPageId, uint32_t count) { + for (uint32_t i = 0; i < count; i++) { + reservePage(info, startPageId + i); + } +} + void mapPage(PagingInfo *info, void *physical, void *virtual, bool userPage); void reservePagesUntilPhysical(uint32_t endPageId) { @@ -67,26 +86,14 @@ kernelVirtualPages = buffer; buffer += sizeof(PagingInfo); memset(kernelPhysicalPages, 0, 2 * sizeof(PagingInfo)); - for (uint32_t i = 0; i < endPageId; i++) { - reservePage(kernelPhysicalPages, i); - } - for (uint32_t i = 0; i < 0x800; i++) { - reservePage(kernelVirtualPages, i + 0xFF800); - } + reservePagesCount(kernelVirtualPages, 0, 1); + reservePagesCount(kernelPhysicalPages, 0, endPageId); + reservePagesCount(kernelVirtualPages, 0xFF800, 0x800); kernelPhysicalPages->pageSearchStart = endPageId; kernelVirtualPages->pageSearchStart = 0; kernelVirtualPages->pageDirectory = pageDirectory; } -void reservePage(PagingInfo *info, uint32_t pageId) { - uint32_t coarsePosition = pageId / 32; - info->isPageAllocated[coarsePosition] |= 1 << (pageId % 32); - if (info->isPageAllocated[coarsePosition] == ~0) { - info->isPageAllocatedCoarse[coarsePosition / 32] |= - 1 << (coarsePosition % 32); - } -} - uint32_t findMultiplePages(PagingInfo *info, uint32_t size) { for (uint32_t veryCoarse = info->pageSearchStart / 1024;; veryCoarse++) { if (info->isPageAllocatedCoarse[veryCoarse] == ~0) { @@ -118,28 +125,26 @@ uint32_t findPage(PagingInfo *info) { return findMultiplePages(info, 1); } -void *kernelMapMultiplePhysicalPages(void *address, uint32_t size) { - uint32_t physicalPageStart = U32(address) >> 12; +void *kernelMapPhysicalCount(void *address, uint32_t size) { + uint32_t physicalPageStart = PAGE_ID(address); + reservePagesCount(kernelPhysicalPages, physicalPageStart, size); uint32_t virtualPageStart = findMultiplePages(kernelVirtualPages, size); + reservePagesCount(kernelVirtualPages, virtualPageStart, size); for (uint32_t i = 0; i < size; i++) { - reservePage(kernelPhysicalPages, physicalPageStart + i); - reservePage(kernelVirtualPages, virtualPageStart + i); + mapPage(kernelVirtualPages, ADDRESS(physicalPageStart + i), + ADDRESS(virtualPageStart + i), false); } - for (uint32_t i = 0; i < size; i++) { - mapPage(kernelVirtualPages, PTR((physicalPageStart + i) << 12), - PTR((virtualPageStart + i) << 12), false); - } - return PTR((virtualPageStart << 12) + (U32(address) & 0xFFF)); + return ADDRESS(virtualPageStart) + PAGE_OFFSET(address); } void *kernelMapPhysical(void *address) { - uint32_t physicalPageId = U32(address) >> 12; + uint32_t physicalPageId = PAGE_ID(address); reservePage(kernelPhysicalPages, physicalPageId); uint32_t virtualPageId = findPage(kernelVirtualPages); reservePage(kernelVirtualPages, virtualPageId); - mapPage(kernelVirtualPages, PTR(physicalPageId << 12), - PTR(virtualPageId << 12), false); - return PTR((virtualPageId << 12) + (U32(address) & 0xFFF)); + mapPage(kernelVirtualPages, ADDRESS(physicalPageId), ADDRESS(virtualPageId), + false); + return ADDRESS(virtualPageId) + PAGE_OFFSET(address); } void mapPage(PagingInfo *info, void *physical, void *virtual, bool userPage) { @@ -148,7 +153,7 @@ if (!directory[address->pageDirectoryIndex].present) { uint32_t newPageTable = findPage(kernelPhysicalPages); reservePage(kernelPhysicalPages, newPageTable); - void *temporary = mapTemporary(PTR(newPageTable << 12)); + void *temporary = mapTemporary(ADDRESS(newPageTable)); memset(temporary, 0, 0x1000); directory[address->pageDirectoryIndex].pageTableID = newPageTable; directory[address->pageDirectoryIndex].present = 1; @@ -156,14 +161,14 @@ directory[address->pageDirectoryIndex].belongsToUserProcess |= userPage; } void *pageTablePhysical = - PTR(directory[address->pageDirectoryIndex].pageTableID << 12); + ADDRESS(directory[address->pageDirectoryIndex].pageTableID); void *temporary = mapTemporary(pageTablePhysical); PageTableEntry *pageTable = temporary; - pageTable[address->pageTableIndex].targetAddress = U32(physical) >> 12; + pageTable[address->pageTableIndex].targetAddress = PAGE_ID(physical); pageTable[address->pageTableIndex].present = 1; pageTable[address->pageTableIndex].writable = 1; pageTable[address->pageTableIndex].belongsToUserProcess = userPage; - invalidatePage(U32(virtual) >> 12); + invalidatePage(PAGE_ID(virtual)); } void *getPage() { @@ -171,26 +176,85 @@ reservePage(kernelPhysicalPages, physical); uint32_t virtual = findPage(kernelVirtualPages); reservePage(kernelVirtualPages, virtual); - mapPage(kernelVirtualPages, PTR(physical << 12), PTR(virtual << 12), false); - return PTR(virtual << 12); + mapPage(kernelVirtualPages, ADDRESS(physical), ADDRESS(virtual), false); + return ADDRESS(virtual); } -void *getMultiplePages(uint32_t count) { - uint32_t virtual = findMultiplePages(kernelVirtualPages, count); +void *getPagesCount(uint32_t count) { + uint32_t virtualPageId = findMultiplePages(kernelVirtualPages, count); + reservePagesCount(kernelVirtualPages, virtualPageId, count); for (uint32_t i = 0; i < count; i++) { - reservePage(kernelVirtualPages, virtual + i); uint32_t physical = findPage(kernelPhysicalPages); reservePage(kernelPhysicalPages, physical); - mapPage(kernelVirtualPages, PTR(physical << 12), - PTR((virtual + i) << 12), false); + mapPage(kernelVirtualPages, ADDRESS(physical), + ADDRESS(virtualPageId + i), false); } - return PTR(virtual << 12); + return ADDRESS(virtualPageId); } -void sharePage(PagingInfo *destination, void *sourceAddress, - void *destinationAddress) { +void *sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress) { PagingInfo *sourcePagingInfo = kernelVirtualPages; void *physicalSource = getPhysicalAddress(sourcePagingInfo->pageDirectory, sourceAddress); + if (!destinationAddress) { + void *target = ADDRESS(findPage(destination)); + mapPage(destination, physicalSource, target, true); + return target + PAGE_OFFSET(sourceAddress); + } mapPage(destination, physicalSource, destinationAddress, true); + return destinationAddress; } + +void unmapSinglePageFrom(PagingInfo *info, void *pageAddress) { + VirtualAddress *address = (void *)&pageAddress; + PageDirectoryEntry *directory = info->pageDirectory; + void *pageTablePhysical = + ADDRESS(directory[address->pageDirectoryIndex].pageTableID); + void *temporary = mapTemporary(pageTablePhysical); + PageTableEntry *pageTable = temporary; + pageTable[address->pageTableIndex].targetAddress = 0; + pageTable[address->pageTableIndex].present = 0; + invalidatePage(PAGE_ID(pageAddress)); +} + +void markPageFree(PagingInfo *info, uint32_t coarse, uint32_t fine, + uint32_t fineBit) { + info->isPageAllocated[coarse] &= ~fineBit; + info->isPageConnectedToNext[coarse] &= ~fineBit; + info->isPageAllocatedCoarse[coarse / 32] &= ~(1 << (coarse % 32)); +} + +void unmapPageFrom(PagingInfo *info, void *address) { + uint32_t pageId = PAGE_ID(address), coarse, fine, fineBit; + do { + coarse = pageId / 32; + fine = pageId % 32; + fineBit = 1 << fine; + markPageFree(info, coarse, fine, fineBit); + unmapSinglePageFrom(info, ADDRESS(pageId)); + } while (info->isPageConnectedToNext[coarse] & fineBit); +} + +void unmapPage(void *pageAddress) { + unmapPageFrom(kernelVirtualPages, pageAddress); +} + +void freePageFrom(PagingInfo *info, void *address) { + uint32_t pageId = PAGE_ID(address), coarse, fine, fineBit; + do { + coarse = pageId / 32; + fine = pageId % 32; + fineBit = 1 << fine; + markPageFree(info, coarse, fine, fineBit); + PageTableEntry *pageTable = mapTemporary( + ADDRESS(info->pageDirectory[PAGE_ID(pageId)].pageTableID)); + uint32_t physicalPageId = pageTable[PAGE_OFFSET(pageId)].targetAddress; + uint32_t physicalFine = physicalPageId % 32; + markPageFree(kernelPhysicalPages, physicalPageId / 32, physicalFine, + 1 << physicalFine); + unmapSinglePageFrom(info, ADDRESS(pageId)); + } while (info->isPageConnectedToNext[coarse] & fineBit); +} + +void freePage(void *address) {} diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index 2ab0784..60d8c0e 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -19,28 +19,34 @@ PageDirectoryEntry *pageDirectory; uint32_t isPageTableInUse[0x20]; uint32_t isPageAllocated[0x8000]; + uint32_t isPageConnectedToNext[0x8000]; uint32_t isPageAllocatedCoarse[0x400]; uint32_t pageSearchStart; } PagingInfo; extern void setupMemory(); extern void reservePagesUntilPhysical(uint32_t endPageId); + extern void memset(void *target, uint8_t byte, uint32_t size); -extern void *kernelMapPhysical(void *address); -extern void *kernelMapMultiplePhysicalPages(void *address, uint32_t size); + extern void *findTarFile(void *fileStart, uint32_t fileSize, char *filename); -extern void *mapPageForNewService(PagingInfo *info, void *virtualTarget); -extern void *malloc(uint32_t size); -extern void free(void *address); + +extern void *kernelMapPhysical(void *address); +extern void *kernelMapPhysicalCount(void *address, uint32_t size); extern void *getPage(); -extern void sharePage(PagingInfo *destination, void *sourceAddress, - void *destinationAddress); +extern void *sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress); +extern void freePage(void *pageAddress); +extern void unmapPage(void *pageAddress); + +extern void free(void *address); +extern void *malloc(uint32_t size); extern void *getPhysicalAddressKernel(void *address); extern void *getPhysicalAddress(PageDirectoryEntry *pageDirectory, void *address); extern uint32_t findPage(PagingInfo *info); extern void *mapTemporary(void *address); -extern void *getMultiplePages(uint32_t size); +extern void *getPagesCount(uint32_t size); #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 33b9b77..f8b6f03 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -37,7 +37,7 @@ } void loadAndScheduleLoader(void *multibootInfo) { - void *address = kernelMapMultiplePhysicalPages(multibootInfo, 4); + void *address = kernelMapPhysicalCount(multibootInfo, 4); initrd = findInitrd(address, &initrdSize); loadInitrdProgram("loader", NULL); } diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c index c6aa5f9..1c63546 100644 --- a/src/kernel/memory/malloc.c +++ b/src/kernel/memory/malloc.c @@ -23,7 +23,7 @@ void *malloc(uint32_t size) { uint32_t sizeBit = LOG2(size) + 1; if (sizeBit > 10) { - return getMultiplePages(((size - 1) >> 12) + 1); + return getPagesCount(((size - 1) >> 12) + 1); } AllocationBlock *block = allocationData[sizeBit], *last = 0; while (1) { @@ -60,7 +60,7 @@ void free(void *location) { AllocationBlock *block = (void *)((uintptr_t)location & ~0xFFF); if (block->magic != ALLOCATION_MAGIC) { - // freePage(location); + freePage(location); return; } uint16_t index = (uint16_t)((uintptr_t)location & 0xFFF) / block->blockSize; diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index 9e528bd..9dca1f3 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -2,6 +2,10 @@ #include #include +#define ADDRESS(pageId) PTR((pageId) << 12) +#define PAGE_ID(address) (U32(address) >> 12) +#define PAGE_OFFSET(address) (U32(address) & 0xFFF) + PageTableEntry *kernelCodePageTable, *kernelDataPageTable; PagingInfo *kernelPhysicalPages, *kernelVirtualPages; @@ -29,18 +33,18 @@ } void *mapTemporary(void *physical) { - kernelDataPageTable[3].targetAddress = U32(physical) >> 12; + kernelDataPageTable[3].targetAddress = PAGE_ID(physical); kernelDataPageTable[3].writable = 1; kernelDataPageTable[3].present = 1; invalidatePage(0xFF803); - return temporaryPage + (U32(physical) & 0xFFF); + return temporaryPage + PAGE_OFFSET(physical); } void *getPhysicalAddress(PageDirectoryEntry *pageDirectory, void *address) { VirtualAddress *virtual = (void *)&address; uint32_t pageTableId = pageDirectory[virtual->pageDirectoryIndex].pageTableID; - PageTableEntry *pageTable = mapTemporary(PTR(pageTableId << 12)); + PageTableEntry *pageTable = mapTemporary(ADDRESS(pageTableId)); uint32_t pageBase = pageTable[virtual->pageTableIndex].targetAddress; return PTR(pageBase << 12 | virtual->pageOffset); } @@ -49,6 +53,21 @@ return getPhysicalAddress(kernelVirtualPages->pageDirectory, address); } +void reservePage(PagingInfo *info, uint32_t pageId) { + uint32_t coarsePosition = pageId / 32; + info->isPageAllocated[coarsePosition] |= 1 << (pageId % 32); + if (info->isPageAllocated[coarsePosition] == ~0) { + info->isPageAllocatedCoarse[coarsePosition / 32] |= + 1 << (coarsePosition % 32); + } +} + +void reservePagesCount(PagingInfo *info, uint32_t startPageId, uint32_t count) { + for (uint32_t i = 0; i < count; i++) { + reservePage(info, startPageId + i); + } +} + void mapPage(PagingInfo *info, void *physical, void *virtual, bool userPage); void reservePagesUntilPhysical(uint32_t endPageId) { @@ -67,26 +86,14 @@ kernelVirtualPages = buffer; buffer += sizeof(PagingInfo); memset(kernelPhysicalPages, 0, 2 * sizeof(PagingInfo)); - for (uint32_t i = 0; i < endPageId; i++) { - reservePage(kernelPhysicalPages, i); - } - for (uint32_t i = 0; i < 0x800; i++) { - reservePage(kernelVirtualPages, i + 0xFF800); - } + reservePagesCount(kernelVirtualPages, 0, 1); + reservePagesCount(kernelPhysicalPages, 0, endPageId); + reservePagesCount(kernelVirtualPages, 0xFF800, 0x800); kernelPhysicalPages->pageSearchStart = endPageId; kernelVirtualPages->pageSearchStart = 0; kernelVirtualPages->pageDirectory = pageDirectory; } -void reservePage(PagingInfo *info, uint32_t pageId) { - uint32_t coarsePosition = pageId / 32; - info->isPageAllocated[coarsePosition] |= 1 << (pageId % 32); - if (info->isPageAllocated[coarsePosition] == ~0) { - info->isPageAllocatedCoarse[coarsePosition / 32] |= - 1 << (coarsePosition % 32); - } -} - uint32_t findMultiplePages(PagingInfo *info, uint32_t size) { for (uint32_t veryCoarse = info->pageSearchStart / 1024;; veryCoarse++) { if (info->isPageAllocatedCoarse[veryCoarse] == ~0) { @@ -118,28 +125,26 @@ uint32_t findPage(PagingInfo *info) { return findMultiplePages(info, 1); } -void *kernelMapMultiplePhysicalPages(void *address, uint32_t size) { - uint32_t physicalPageStart = U32(address) >> 12; +void *kernelMapPhysicalCount(void *address, uint32_t size) { + uint32_t physicalPageStart = PAGE_ID(address); + reservePagesCount(kernelPhysicalPages, physicalPageStart, size); uint32_t virtualPageStart = findMultiplePages(kernelVirtualPages, size); + reservePagesCount(kernelVirtualPages, virtualPageStart, size); for (uint32_t i = 0; i < size; i++) { - reservePage(kernelPhysicalPages, physicalPageStart + i); - reservePage(kernelVirtualPages, virtualPageStart + i); + mapPage(kernelVirtualPages, ADDRESS(physicalPageStart + i), + ADDRESS(virtualPageStart + i), false); } - for (uint32_t i = 0; i < size; i++) { - mapPage(kernelVirtualPages, PTR((physicalPageStart + i) << 12), - PTR((virtualPageStart + i) << 12), false); - } - return PTR((virtualPageStart << 12) + (U32(address) & 0xFFF)); + return ADDRESS(virtualPageStart) + PAGE_OFFSET(address); } void *kernelMapPhysical(void *address) { - uint32_t physicalPageId = U32(address) >> 12; + uint32_t physicalPageId = PAGE_ID(address); reservePage(kernelPhysicalPages, physicalPageId); uint32_t virtualPageId = findPage(kernelVirtualPages); reservePage(kernelVirtualPages, virtualPageId); - mapPage(kernelVirtualPages, PTR(physicalPageId << 12), - PTR(virtualPageId << 12), false); - return PTR((virtualPageId << 12) + (U32(address) & 0xFFF)); + mapPage(kernelVirtualPages, ADDRESS(physicalPageId), ADDRESS(virtualPageId), + false); + return ADDRESS(virtualPageId) + PAGE_OFFSET(address); } void mapPage(PagingInfo *info, void *physical, void *virtual, bool userPage) { @@ -148,7 +153,7 @@ if (!directory[address->pageDirectoryIndex].present) { uint32_t newPageTable = findPage(kernelPhysicalPages); reservePage(kernelPhysicalPages, newPageTable); - void *temporary = mapTemporary(PTR(newPageTable << 12)); + void *temporary = mapTemporary(ADDRESS(newPageTable)); memset(temporary, 0, 0x1000); directory[address->pageDirectoryIndex].pageTableID = newPageTable; directory[address->pageDirectoryIndex].present = 1; @@ -156,14 +161,14 @@ directory[address->pageDirectoryIndex].belongsToUserProcess |= userPage; } void *pageTablePhysical = - PTR(directory[address->pageDirectoryIndex].pageTableID << 12); + ADDRESS(directory[address->pageDirectoryIndex].pageTableID); void *temporary = mapTemporary(pageTablePhysical); PageTableEntry *pageTable = temporary; - pageTable[address->pageTableIndex].targetAddress = U32(physical) >> 12; + pageTable[address->pageTableIndex].targetAddress = PAGE_ID(physical); pageTable[address->pageTableIndex].present = 1; pageTable[address->pageTableIndex].writable = 1; pageTable[address->pageTableIndex].belongsToUserProcess = userPage; - invalidatePage(U32(virtual) >> 12); + invalidatePage(PAGE_ID(virtual)); } void *getPage() { @@ -171,26 +176,85 @@ reservePage(kernelPhysicalPages, physical); uint32_t virtual = findPage(kernelVirtualPages); reservePage(kernelVirtualPages, virtual); - mapPage(kernelVirtualPages, PTR(physical << 12), PTR(virtual << 12), false); - return PTR(virtual << 12); + mapPage(kernelVirtualPages, ADDRESS(physical), ADDRESS(virtual), false); + return ADDRESS(virtual); } -void *getMultiplePages(uint32_t count) { - uint32_t virtual = findMultiplePages(kernelVirtualPages, count); +void *getPagesCount(uint32_t count) { + uint32_t virtualPageId = findMultiplePages(kernelVirtualPages, count); + reservePagesCount(kernelVirtualPages, virtualPageId, count); for (uint32_t i = 0; i < count; i++) { - reservePage(kernelVirtualPages, virtual + i); uint32_t physical = findPage(kernelPhysicalPages); reservePage(kernelPhysicalPages, physical); - mapPage(kernelVirtualPages, PTR(physical << 12), - PTR((virtual + i) << 12), false); + mapPage(kernelVirtualPages, ADDRESS(physical), + ADDRESS(virtualPageId + i), false); } - return PTR(virtual << 12); + return ADDRESS(virtualPageId); } -void sharePage(PagingInfo *destination, void *sourceAddress, - void *destinationAddress) { +void *sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress) { PagingInfo *sourcePagingInfo = kernelVirtualPages; void *physicalSource = getPhysicalAddress(sourcePagingInfo->pageDirectory, sourceAddress); + if (!destinationAddress) { + void *target = ADDRESS(findPage(destination)); + mapPage(destination, physicalSource, target, true); + return target + PAGE_OFFSET(sourceAddress); + } mapPage(destination, physicalSource, destinationAddress, true); + return destinationAddress; } + +void unmapSinglePageFrom(PagingInfo *info, void *pageAddress) { + VirtualAddress *address = (void *)&pageAddress; + PageDirectoryEntry *directory = info->pageDirectory; + void *pageTablePhysical = + ADDRESS(directory[address->pageDirectoryIndex].pageTableID); + void *temporary = mapTemporary(pageTablePhysical); + PageTableEntry *pageTable = temporary; + pageTable[address->pageTableIndex].targetAddress = 0; + pageTable[address->pageTableIndex].present = 0; + invalidatePage(PAGE_ID(pageAddress)); +} + +void markPageFree(PagingInfo *info, uint32_t coarse, uint32_t fine, + uint32_t fineBit) { + info->isPageAllocated[coarse] &= ~fineBit; + info->isPageConnectedToNext[coarse] &= ~fineBit; + info->isPageAllocatedCoarse[coarse / 32] &= ~(1 << (coarse % 32)); +} + +void unmapPageFrom(PagingInfo *info, void *address) { + uint32_t pageId = PAGE_ID(address), coarse, fine, fineBit; + do { + coarse = pageId / 32; + fine = pageId % 32; + fineBit = 1 << fine; + markPageFree(info, coarse, fine, fineBit); + unmapSinglePageFrom(info, ADDRESS(pageId)); + } while (info->isPageConnectedToNext[coarse] & fineBit); +} + +void unmapPage(void *pageAddress) { + unmapPageFrom(kernelVirtualPages, pageAddress); +} + +void freePageFrom(PagingInfo *info, void *address) { + uint32_t pageId = PAGE_ID(address), coarse, fine, fineBit; + do { + coarse = pageId / 32; + fine = pageId % 32; + fineBit = 1 << fine; + markPageFree(info, coarse, fine, fineBit); + PageTableEntry *pageTable = mapTemporary( + ADDRESS(info->pageDirectory[PAGE_ID(pageId)].pageTableID)); + uint32_t physicalPageId = pageTable[PAGE_OFFSET(pageId)].targetAddress; + uint32_t physicalFine = physicalPageId % 32; + markPageFree(kernelPhysicalPages, physicalPageId / 32, physicalFine, + 1 << physicalFine); + unmapSinglePageFrom(info, ADDRESS(pageId)); + } while (info->isPageConnectedToNext[coarse] & fineBit); +} + +void freePage(void *address) {} diff --git a/src/kernel/multiboot/multiboot.c b/src/kernel/multiboot/multiboot.c index f9ce722..794f42c 100644 --- a/src/kernel/multiboot/multiboot.c +++ b/src/kernel/multiboot/multiboot.c @@ -10,7 +10,7 @@ "initrd")) { MultibootModuleTag *module = (void *)tag; uint32_t moduleSize = module->moduleEnd - module->moduleStart; - void *moduleLocation = kernelMapMultiplePhysicalPages( + void *moduleLocation = kernelMapPhysicalCount( PTR(module->moduleStart), PAGE_COUNT(moduleSize)); *fileSize = moduleSize; return moduleLocation; diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index 2ab0784..60d8c0e 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -19,28 +19,34 @@ PageDirectoryEntry *pageDirectory; uint32_t isPageTableInUse[0x20]; uint32_t isPageAllocated[0x8000]; + uint32_t isPageConnectedToNext[0x8000]; uint32_t isPageAllocatedCoarse[0x400]; uint32_t pageSearchStart; } PagingInfo; extern void setupMemory(); extern void reservePagesUntilPhysical(uint32_t endPageId); + extern void memset(void *target, uint8_t byte, uint32_t size); -extern void *kernelMapPhysical(void *address); -extern void *kernelMapMultiplePhysicalPages(void *address, uint32_t size); + extern void *findTarFile(void *fileStart, uint32_t fileSize, char *filename); -extern void *mapPageForNewService(PagingInfo *info, void *virtualTarget); -extern void *malloc(uint32_t size); -extern void free(void *address); + +extern void *kernelMapPhysical(void *address); +extern void *kernelMapPhysicalCount(void *address, uint32_t size); extern void *getPage(); -extern void sharePage(PagingInfo *destination, void *sourceAddress, - void *destinationAddress); +extern void *sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress); +extern void freePage(void *pageAddress); +extern void unmapPage(void *pageAddress); + +extern void free(void *address); +extern void *malloc(uint32_t size); extern void *getPhysicalAddressKernel(void *address); extern void *getPhysicalAddress(PageDirectoryEntry *pageDirectory, void *address); extern uint32_t findPage(PagingInfo *info); extern void *mapTemporary(void *address); -extern void *getMultiplePages(uint32_t size); +extern void *getPagesCount(uint32_t size); #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 33b9b77..f8b6f03 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -37,7 +37,7 @@ } void loadAndScheduleLoader(void *multibootInfo) { - void *address = kernelMapMultiplePhysicalPages(multibootInfo, 4); + void *address = kernelMapPhysicalCount(multibootInfo, 4); initrd = findInitrd(address, &initrdSize); loadInitrdProgram("loader", NULL); } diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c index c6aa5f9..1c63546 100644 --- a/src/kernel/memory/malloc.c +++ b/src/kernel/memory/malloc.c @@ -23,7 +23,7 @@ void *malloc(uint32_t size) { uint32_t sizeBit = LOG2(size) + 1; if (sizeBit > 10) { - return getMultiplePages(((size - 1) >> 12) + 1); + return getPagesCount(((size - 1) >> 12) + 1); } AllocationBlock *block = allocationData[sizeBit], *last = 0; while (1) { @@ -60,7 +60,7 @@ void free(void *location) { AllocationBlock *block = (void *)((uintptr_t)location & ~0xFFF); if (block->magic != ALLOCATION_MAGIC) { - // freePage(location); + freePage(location); return; } uint16_t index = (uint16_t)((uintptr_t)location & 0xFFF) / block->blockSize; diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index 9e528bd..9dca1f3 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -2,6 +2,10 @@ #include #include +#define ADDRESS(pageId) PTR((pageId) << 12) +#define PAGE_ID(address) (U32(address) >> 12) +#define PAGE_OFFSET(address) (U32(address) & 0xFFF) + PageTableEntry *kernelCodePageTable, *kernelDataPageTable; PagingInfo *kernelPhysicalPages, *kernelVirtualPages; @@ -29,18 +33,18 @@ } void *mapTemporary(void *physical) { - kernelDataPageTable[3].targetAddress = U32(physical) >> 12; + kernelDataPageTable[3].targetAddress = PAGE_ID(physical); kernelDataPageTable[3].writable = 1; kernelDataPageTable[3].present = 1; invalidatePage(0xFF803); - return temporaryPage + (U32(physical) & 0xFFF); + return temporaryPage + PAGE_OFFSET(physical); } void *getPhysicalAddress(PageDirectoryEntry *pageDirectory, void *address) { VirtualAddress *virtual = (void *)&address; uint32_t pageTableId = pageDirectory[virtual->pageDirectoryIndex].pageTableID; - PageTableEntry *pageTable = mapTemporary(PTR(pageTableId << 12)); + PageTableEntry *pageTable = mapTemporary(ADDRESS(pageTableId)); uint32_t pageBase = pageTable[virtual->pageTableIndex].targetAddress; return PTR(pageBase << 12 | virtual->pageOffset); } @@ -49,6 +53,21 @@ return getPhysicalAddress(kernelVirtualPages->pageDirectory, address); } +void reservePage(PagingInfo *info, uint32_t pageId) { + uint32_t coarsePosition = pageId / 32; + info->isPageAllocated[coarsePosition] |= 1 << (pageId % 32); + if (info->isPageAllocated[coarsePosition] == ~0) { + info->isPageAllocatedCoarse[coarsePosition / 32] |= + 1 << (coarsePosition % 32); + } +} + +void reservePagesCount(PagingInfo *info, uint32_t startPageId, uint32_t count) { + for (uint32_t i = 0; i < count; i++) { + reservePage(info, startPageId + i); + } +} + void mapPage(PagingInfo *info, void *physical, void *virtual, bool userPage); void reservePagesUntilPhysical(uint32_t endPageId) { @@ -67,26 +86,14 @@ kernelVirtualPages = buffer; buffer += sizeof(PagingInfo); memset(kernelPhysicalPages, 0, 2 * sizeof(PagingInfo)); - for (uint32_t i = 0; i < endPageId; i++) { - reservePage(kernelPhysicalPages, i); - } - for (uint32_t i = 0; i < 0x800; i++) { - reservePage(kernelVirtualPages, i + 0xFF800); - } + reservePagesCount(kernelVirtualPages, 0, 1); + reservePagesCount(kernelPhysicalPages, 0, endPageId); + reservePagesCount(kernelVirtualPages, 0xFF800, 0x800); kernelPhysicalPages->pageSearchStart = endPageId; kernelVirtualPages->pageSearchStart = 0; kernelVirtualPages->pageDirectory = pageDirectory; } -void reservePage(PagingInfo *info, uint32_t pageId) { - uint32_t coarsePosition = pageId / 32; - info->isPageAllocated[coarsePosition] |= 1 << (pageId % 32); - if (info->isPageAllocated[coarsePosition] == ~0) { - info->isPageAllocatedCoarse[coarsePosition / 32] |= - 1 << (coarsePosition % 32); - } -} - uint32_t findMultiplePages(PagingInfo *info, uint32_t size) { for (uint32_t veryCoarse = info->pageSearchStart / 1024;; veryCoarse++) { if (info->isPageAllocatedCoarse[veryCoarse] == ~0) { @@ -118,28 +125,26 @@ uint32_t findPage(PagingInfo *info) { return findMultiplePages(info, 1); } -void *kernelMapMultiplePhysicalPages(void *address, uint32_t size) { - uint32_t physicalPageStart = U32(address) >> 12; +void *kernelMapPhysicalCount(void *address, uint32_t size) { + uint32_t physicalPageStart = PAGE_ID(address); + reservePagesCount(kernelPhysicalPages, physicalPageStart, size); uint32_t virtualPageStart = findMultiplePages(kernelVirtualPages, size); + reservePagesCount(kernelVirtualPages, virtualPageStart, size); for (uint32_t i = 0; i < size; i++) { - reservePage(kernelPhysicalPages, physicalPageStart + i); - reservePage(kernelVirtualPages, virtualPageStart + i); + mapPage(kernelVirtualPages, ADDRESS(physicalPageStart + i), + ADDRESS(virtualPageStart + i), false); } - for (uint32_t i = 0; i < size; i++) { - mapPage(kernelVirtualPages, PTR((physicalPageStart + i) << 12), - PTR((virtualPageStart + i) << 12), false); - } - return PTR((virtualPageStart << 12) + (U32(address) & 0xFFF)); + return ADDRESS(virtualPageStart) + PAGE_OFFSET(address); } void *kernelMapPhysical(void *address) { - uint32_t physicalPageId = U32(address) >> 12; + uint32_t physicalPageId = PAGE_ID(address); reservePage(kernelPhysicalPages, physicalPageId); uint32_t virtualPageId = findPage(kernelVirtualPages); reservePage(kernelVirtualPages, virtualPageId); - mapPage(kernelVirtualPages, PTR(physicalPageId << 12), - PTR(virtualPageId << 12), false); - return PTR((virtualPageId << 12) + (U32(address) & 0xFFF)); + mapPage(kernelVirtualPages, ADDRESS(physicalPageId), ADDRESS(virtualPageId), + false); + return ADDRESS(virtualPageId) + PAGE_OFFSET(address); } void mapPage(PagingInfo *info, void *physical, void *virtual, bool userPage) { @@ -148,7 +153,7 @@ if (!directory[address->pageDirectoryIndex].present) { uint32_t newPageTable = findPage(kernelPhysicalPages); reservePage(kernelPhysicalPages, newPageTable); - void *temporary = mapTemporary(PTR(newPageTable << 12)); + void *temporary = mapTemporary(ADDRESS(newPageTable)); memset(temporary, 0, 0x1000); directory[address->pageDirectoryIndex].pageTableID = newPageTable; directory[address->pageDirectoryIndex].present = 1; @@ -156,14 +161,14 @@ directory[address->pageDirectoryIndex].belongsToUserProcess |= userPage; } void *pageTablePhysical = - PTR(directory[address->pageDirectoryIndex].pageTableID << 12); + ADDRESS(directory[address->pageDirectoryIndex].pageTableID); void *temporary = mapTemporary(pageTablePhysical); PageTableEntry *pageTable = temporary; - pageTable[address->pageTableIndex].targetAddress = U32(physical) >> 12; + pageTable[address->pageTableIndex].targetAddress = PAGE_ID(physical); pageTable[address->pageTableIndex].present = 1; pageTable[address->pageTableIndex].writable = 1; pageTable[address->pageTableIndex].belongsToUserProcess = userPage; - invalidatePage(U32(virtual) >> 12); + invalidatePage(PAGE_ID(virtual)); } void *getPage() { @@ -171,26 +176,85 @@ reservePage(kernelPhysicalPages, physical); uint32_t virtual = findPage(kernelVirtualPages); reservePage(kernelVirtualPages, virtual); - mapPage(kernelVirtualPages, PTR(physical << 12), PTR(virtual << 12), false); - return PTR(virtual << 12); + mapPage(kernelVirtualPages, ADDRESS(physical), ADDRESS(virtual), false); + return ADDRESS(virtual); } -void *getMultiplePages(uint32_t count) { - uint32_t virtual = findMultiplePages(kernelVirtualPages, count); +void *getPagesCount(uint32_t count) { + uint32_t virtualPageId = findMultiplePages(kernelVirtualPages, count); + reservePagesCount(kernelVirtualPages, virtualPageId, count); for (uint32_t i = 0; i < count; i++) { - reservePage(kernelVirtualPages, virtual + i); uint32_t physical = findPage(kernelPhysicalPages); reservePage(kernelPhysicalPages, physical); - mapPage(kernelVirtualPages, PTR(physical << 12), - PTR((virtual + i) << 12), false); + mapPage(kernelVirtualPages, ADDRESS(physical), + ADDRESS(virtualPageId + i), false); } - return PTR(virtual << 12); + return ADDRESS(virtualPageId); } -void sharePage(PagingInfo *destination, void *sourceAddress, - void *destinationAddress) { +void *sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress) { PagingInfo *sourcePagingInfo = kernelVirtualPages; void *physicalSource = getPhysicalAddress(sourcePagingInfo->pageDirectory, sourceAddress); + if (!destinationAddress) { + void *target = ADDRESS(findPage(destination)); + mapPage(destination, physicalSource, target, true); + return target + PAGE_OFFSET(sourceAddress); + } mapPage(destination, physicalSource, destinationAddress, true); + return destinationAddress; } + +void unmapSinglePageFrom(PagingInfo *info, void *pageAddress) { + VirtualAddress *address = (void *)&pageAddress; + PageDirectoryEntry *directory = info->pageDirectory; + void *pageTablePhysical = + ADDRESS(directory[address->pageDirectoryIndex].pageTableID); + void *temporary = mapTemporary(pageTablePhysical); + PageTableEntry *pageTable = temporary; + pageTable[address->pageTableIndex].targetAddress = 0; + pageTable[address->pageTableIndex].present = 0; + invalidatePage(PAGE_ID(pageAddress)); +} + +void markPageFree(PagingInfo *info, uint32_t coarse, uint32_t fine, + uint32_t fineBit) { + info->isPageAllocated[coarse] &= ~fineBit; + info->isPageConnectedToNext[coarse] &= ~fineBit; + info->isPageAllocatedCoarse[coarse / 32] &= ~(1 << (coarse % 32)); +} + +void unmapPageFrom(PagingInfo *info, void *address) { + uint32_t pageId = PAGE_ID(address), coarse, fine, fineBit; + do { + coarse = pageId / 32; + fine = pageId % 32; + fineBit = 1 << fine; + markPageFree(info, coarse, fine, fineBit); + unmapSinglePageFrom(info, ADDRESS(pageId)); + } while (info->isPageConnectedToNext[coarse] & fineBit); +} + +void unmapPage(void *pageAddress) { + unmapPageFrom(kernelVirtualPages, pageAddress); +} + +void freePageFrom(PagingInfo *info, void *address) { + uint32_t pageId = PAGE_ID(address), coarse, fine, fineBit; + do { + coarse = pageId / 32; + fine = pageId % 32; + fineBit = 1 << fine; + markPageFree(info, coarse, fine, fineBit); + PageTableEntry *pageTable = mapTemporary( + ADDRESS(info->pageDirectory[PAGE_ID(pageId)].pageTableID)); + uint32_t physicalPageId = pageTable[PAGE_OFFSET(pageId)].targetAddress; + uint32_t physicalFine = physicalPageId % 32; + markPageFree(kernelPhysicalPages, physicalPageId / 32, physicalFine, + 1 << physicalFine); + unmapSinglePageFrom(info, ADDRESS(pageId)); + } while (info->isPageConnectedToNext[coarse] & fineBit); +} + +void freePage(void *address) {} diff --git a/src/kernel/multiboot/multiboot.c b/src/kernel/multiboot/multiboot.c index f9ce722..794f42c 100644 --- a/src/kernel/multiboot/multiboot.c +++ b/src/kernel/multiboot/multiboot.c @@ -10,7 +10,7 @@ "initrd")) { MultibootModuleTag *module = (void *)tag; uint32_t moduleSize = module->moduleEnd - module->moduleStart; - void *moduleLocation = kernelMapMultiplePhysicalPages( + void *moduleLocation = kernelMapPhysicalCount( PTR(module->moduleStart), PAGE_COUNT(moduleSize)); *fileSize = moduleSize; return moduleLocation; diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c index a61ff1d..db0251e 100644 --- a/src/kernel/service/services.c +++ b/src/kernel/service/services.c @@ -12,6 +12,9 @@ Syscall *currentSyscall; void resume(Syscall *syscall) { + if (U32(syscall) < 0x1000) { + asm("hlt" ::"a"(syscall)); + } currentSyscall = syscall; runFunction(); } @@ -27,9 +30,7 @@ service->pagingInfo.pageDirectory = malloc(0x1000); service->name = serviceName; // todo: make this unwritable! - // todo: use functionsStart as the reference - sharePage(&(service->pagingInfo), PTR(0xFFC02000), - PTR(0xFFC02000)); // functionsStart, functionsStart); + sharePage(&(service->pagingInfo), &functionsStart, &functionsStart); for (uint32_t i = 0; i < header->programHeaderEntryCount; i++) { for (uint32_t page = 0; page < programHeader->segmentMemorySize; page += 0x1000) { diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index 2ab0784..60d8c0e 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -19,28 +19,34 @@ PageDirectoryEntry *pageDirectory; uint32_t isPageTableInUse[0x20]; uint32_t isPageAllocated[0x8000]; + uint32_t isPageConnectedToNext[0x8000]; uint32_t isPageAllocatedCoarse[0x400]; uint32_t pageSearchStart; } PagingInfo; extern void setupMemory(); extern void reservePagesUntilPhysical(uint32_t endPageId); + extern void memset(void *target, uint8_t byte, uint32_t size); -extern void *kernelMapPhysical(void *address); -extern void *kernelMapMultiplePhysicalPages(void *address, uint32_t size); + extern void *findTarFile(void *fileStart, uint32_t fileSize, char *filename); -extern void *mapPageForNewService(PagingInfo *info, void *virtualTarget); -extern void *malloc(uint32_t size); -extern void free(void *address); + +extern void *kernelMapPhysical(void *address); +extern void *kernelMapPhysicalCount(void *address, uint32_t size); extern void *getPage(); -extern void sharePage(PagingInfo *destination, void *sourceAddress, - void *destinationAddress); +extern void *sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress); +extern void freePage(void *pageAddress); +extern void unmapPage(void *pageAddress); + +extern void free(void *address); +extern void *malloc(uint32_t size); extern void *getPhysicalAddressKernel(void *address); extern void *getPhysicalAddress(PageDirectoryEntry *pageDirectory, void *address); extern uint32_t findPage(PagingInfo *info); extern void *mapTemporary(void *address); -extern void *getMultiplePages(uint32_t size); +extern void *getPagesCount(uint32_t size); #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 33b9b77..f8b6f03 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -37,7 +37,7 @@ } void loadAndScheduleLoader(void *multibootInfo) { - void *address = kernelMapMultiplePhysicalPages(multibootInfo, 4); + void *address = kernelMapPhysicalCount(multibootInfo, 4); initrd = findInitrd(address, &initrdSize); loadInitrdProgram("loader", NULL); } diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c index c6aa5f9..1c63546 100644 --- a/src/kernel/memory/malloc.c +++ b/src/kernel/memory/malloc.c @@ -23,7 +23,7 @@ void *malloc(uint32_t size) { uint32_t sizeBit = LOG2(size) + 1; if (sizeBit > 10) { - return getMultiplePages(((size - 1) >> 12) + 1); + return getPagesCount(((size - 1) >> 12) + 1); } AllocationBlock *block = allocationData[sizeBit], *last = 0; while (1) { @@ -60,7 +60,7 @@ void free(void *location) { AllocationBlock *block = (void *)((uintptr_t)location & ~0xFFF); if (block->magic != ALLOCATION_MAGIC) { - // freePage(location); + freePage(location); return; } uint16_t index = (uint16_t)((uintptr_t)location & 0xFFF) / block->blockSize; diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index 9e528bd..9dca1f3 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -2,6 +2,10 @@ #include #include +#define ADDRESS(pageId) PTR((pageId) << 12) +#define PAGE_ID(address) (U32(address) >> 12) +#define PAGE_OFFSET(address) (U32(address) & 0xFFF) + PageTableEntry *kernelCodePageTable, *kernelDataPageTable; PagingInfo *kernelPhysicalPages, *kernelVirtualPages; @@ -29,18 +33,18 @@ } void *mapTemporary(void *physical) { - kernelDataPageTable[3].targetAddress = U32(physical) >> 12; + kernelDataPageTable[3].targetAddress = PAGE_ID(physical); kernelDataPageTable[3].writable = 1; kernelDataPageTable[3].present = 1; invalidatePage(0xFF803); - return temporaryPage + (U32(physical) & 0xFFF); + return temporaryPage + PAGE_OFFSET(physical); } void *getPhysicalAddress(PageDirectoryEntry *pageDirectory, void *address) { VirtualAddress *virtual = (void *)&address; uint32_t pageTableId = pageDirectory[virtual->pageDirectoryIndex].pageTableID; - PageTableEntry *pageTable = mapTemporary(PTR(pageTableId << 12)); + PageTableEntry *pageTable = mapTemporary(ADDRESS(pageTableId)); uint32_t pageBase = pageTable[virtual->pageTableIndex].targetAddress; return PTR(pageBase << 12 | virtual->pageOffset); } @@ -49,6 +53,21 @@ return getPhysicalAddress(kernelVirtualPages->pageDirectory, address); } +void reservePage(PagingInfo *info, uint32_t pageId) { + uint32_t coarsePosition = pageId / 32; + info->isPageAllocated[coarsePosition] |= 1 << (pageId % 32); + if (info->isPageAllocated[coarsePosition] == ~0) { + info->isPageAllocatedCoarse[coarsePosition / 32] |= + 1 << (coarsePosition % 32); + } +} + +void reservePagesCount(PagingInfo *info, uint32_t startPageId, uint32_t count) { + for (uint32_t i = 0; i < count; i++) { + reservePage(info, startPageId + i); + } +} + void mapPage(PagingInfo *info, void *physical, void *virtual, bool userPage); void reservePagesUntilPhysical(uint32_t endPageId) { @@ -67,26 +86,14 @@ kernelVirtualPages = buffer; buffer += sizeof(PagingInfo); memset(kernelPhysicalPages, 0, 2 * sizeof(PagingInfo)); - for (uint32_t i = 0; i < endPageId; i++) { - reservePage(kernelPhysicalPages, i); - } - for (uint32_t i = 0; i < 0x800; i++) { - reservePage(kernelVirtualPages, i + 0xFF800); - } + reservePagesCount(kernelVirtualPages, 0, 1); + reservePagesCount(kernelPhysicalPages, 0, endPageId); + reservePagesCount(kernelVirtualPages, 0xFF800, 0x800); kernelPhysicalPages->pageSearchStart = endPageId; kernelVirtualPages->pageSearchStart = 0; kernelVirtualPages->pageDirectory = pageDirectory; } -void reservePage(PagingInfo *info, uint32_t pageId) { - uint32_t coarsePosition = pageId / 32; - info->isPageAllocated[coarsePosition] |= 1 << (pageId % 32); - if (info->isPageAllocated[coarsePosition] == ~0) { - info->isPageAllocatedCoarse[coarsePosition / 32] |= - 1 << (coarsePosition % 32); - } -} - uint32_t findMultiplePages(PagingInfo *info, uint32_t size) { for (uint32_t veryCoarse = info->pageSearchStart / 1024;; veryCoarse++) { if (info->isPageAllocatedCoarse[veryCoarse] == ~0) { @@ -118,28 +125,26 @@ uint32_t findPage(PagingInfo *info) { return findMultiplePages(info, 1); } -void *kernelMapMultiplePhysicalPages(void *address, uint32_t size) { - uint32_t physicalPageStart = U32(address) >> 12; +void *kernelMapPhysicalCount(void *address, uint32_t size) { + uint32_t physicalPageStart = PAGE_ID(address); + reservePagesCount(kernelPhysicalPages, physicalPageStart, size); uint32_t virtualPageStart = findMultiplePages(kernelVirtualPages, size); + reservePagesCount(kernelVirtualPages, virtualPageStart, size); for (uint32_t i = 0; i < size; i++) { - reservePage(kernelPhysicalPages, physicalPageStart + i); - reservePage(kernelVirtualPages, virtualPageStart + i); + mapPage(kernelVirtualPages, ADDRESS(physicalPageStart + i), + ADDRESS(virtualPageStart + i), false); } - for (uint32_t i = 0; i < size; i++) { - mapPage(kernelVirtualPages, PTR((physicalPageStart + i) << 12), - PTR((virtualPageStart + i) << 12), false); - } - return PTR((virtualPageStart << 12) + (U32(address) & 0xFFF)); + return ADDRESS(virtualPageStart) + PAGE_OFFSET(address); } void *kernelMapPhysical(void *address) { - uint32_t physicalPageId = U32(address) >> 12; + uint32_t physicalPageId = PAGE_ID(address); reservePage(kernelPhysicalPages, physicalPageId); uint32_t virtualPageId = findPage(kernelVirtualPages); reservePage(kernelVirtualPages, virtualPageId); - mapPage(kernelVirtualPages, PTR(physicalPageId << 12), - PTR(virtualPageId << 12), false); - return PTR((virtualPageId << 12) + (U32(address) & 0xFFF)); + mapPage(kernelVirtualPages, ADDRESS(physicalPageId), ADDRESS(virtualPageId), + false); + return ADDRESS(virtualPageId) + PAGE_OFFSET(address); } void mapPage(PagingInfo *info, void *physical, void *virtual, bool userPage) { @@ -148,7 +153,7 @@ if (!directory[address->pageDirectoryIndex].present) { uint32_t newPageTable = findPage(kernelPhysicalPages); reservePage(kernelPhysicalPages, newPageTable); - void *temporary = mapTemporary(PTR(newPageTable << 12)); + void *temporary = mapTemporary(ADDRESS(newPageTable)); memset(temporary, 0, 0x1000); directory[address->pageDirectoryIndex].pageTableID = newPageTable; directory[address->pageDirectoryIndex].present = 1; @@ -156,14 +161,14 @@ directory[address->pageDirectoryIndex].belongsToUserProcess |= userPage; } void *pageTablePhysical = - PTR(directory[address->pageDirectoryIndex].pageTableID << 12); + ADDRESS(directory[address->pageDirectoryIndex].pageTableID); void *temporary = mapTemporary(pageTablePhysical); PageTableEntry *pageTable = temporary; - pageTable[address->pageTableIndex].targetAddress = U32(physical) >> 12; + pageTable[address->pageTableIndex].targetAddress = PAGE_ID(physical); pageTable[address->pageTableIndex].present = 1; pageTable[address->pageTableIndex].writable = 1; pageTable[address->pageTableIndex].belongsToUserProcess = userPage; - invalidatePage(U32(virtual) >> 12); + invalidatePage(PAGE_ID(virtual)); } void *getPage() { @@ -171,26 +176,85 @@ reservePage(kernelPhysicalPages, physical); uint32_t virtual = findPage(kernelVirtualPages); reservePage(kernelVirtualPages, virtual); - mapPage(kernelVirtualPages, PTR(physical << 12), PTR(virtual << 12), false); - return PTR(virtual << 12); + mapPage(kernelVirtualPages, ADDRESS(physical), ADDRESS(virtual), false); + return ADDRESS(virtual); } -void *getMultiplePages(uint32_t count) { - uint32_t virtual = findMultiplePages(kernelVirtualPages, count); +void *getPagesCount(uint32_t count) { + uint32_t virtualPageId = findMultiplePages(kernelVirtualPages, count); + reservePagesCount(kernelVirtualPages, virtualPageId, count); for (uint32_t i = 0; i < count; i++) { - reservePage(kernelVirtualPages, virtual + i); uint32_t physical = findPage(kernelPhysicalPages); reservePage(kernelPhysicalPages, physical); - mapPage(kernelVirtualPages, PTR(physical << 12), - PTR((virtual + i) << 12), false); + mapPage(kernelVirtualPages, ADDRESS(physical), + ADDRESS(virtualPageId + i), false); } - return PTR(virtual << 12); + return ADDRESS(virtualPageId); } -void sharePage(PagingInfo *destination, void *sourceAddress, - void *destinationAddress) { +void *sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress) { PagingInfo *sourcePagingInfo = kernelVirtualPages; void *physicalSource = getPhysicalAddress(sourcePagingInfo->pageDirectory, sourceAddress); + if (!destinationAddress) { + void *target = ADDRESS(findPage(destination)); + mapPage(destination, physicalSource, target, true); + return target + PAGE_OFFSET(sourceAddress); + } mapPage(destination, physicalSource, destinationAddress, true); + return destinationAddress; } + +void unmapSinglePageFrom(PagingInfo *info, void *pageAddress) { + VirtualAddress *address = (void *)&pageAddress; + PageDirectoryEntry *directory = info->pageDirectory; + void *pageTablePhysical = + ADDRESS(directory[address->pageDirectoryIndex].pageTableID); + void *temporary = mapTemporary(pageTablePhysical); + PageTableEntry *pageTable = temporary; + pageTable[address->pageTableIndex].targetAddress = 0; + pageTable[address->pageTableIndex].present = 0; + invalidatePage(PAGE_ID(pageAddress)); +} + +void markPageFree(PagingInfo *info, uint32_t coarse, uint32_t fine, + uint32_t fineBit) { + info->isPageAllocated[coarse] &= ~fineBit; + info->isPageConnectedToNext[coarse] &= ~fineBit; + info->isPageAllocatedCoarse[coarse / 32] &= ~(1 << (coarse % 32)); +} + +void unmapPageFrom(PagingInfo *info, void *address) { + uint32_t pageId = PAGE_ID(address), coarse, fine, fineBit; + do { + coarse = pageId / 32; + fine = pageId % 32; + fineBit = 1 << fine; + markPageFree(info, coarse, fine, fineBit); + unmapSinglePageFrom(info, ADDRESS(pageId)); + } while (info->isPageConnectedToNext[coarse] & fineBit); +} + +void unmapPage(void *pageAddress) { + unmapPageFrom(kernelVirtualPages, pageAddress); +} + +void freePageFrom(PagingInfo *info, void *address) { + uint32_t pageId = PAGE_ID(address), coarse, fine, fineBit; + do { + coarse = pageId / 32; + fine = pageId % 32; + fineBit = 1 << fine; + markPageFree(info, coarse, fine, fineBit); + PageTableEntry *pageTable = mapTemporary( + ADDRESS(info->pageDirectory[PAGE_ID(pageId)].pageTableID)); + uint32_t physicalPageId = pageTable[PAGE_OFFSET(pageId)].targetAddress; + uint32_t physicalFine = physicalPageId % 32; + markPageFree(kernelPhysicalPages, physicalPageId / 32, physicalFine, + 1 << physicalFine); + unmapSinglePageFrom(info, ADDRESS(pageId)); + } while (info->isPageConnectedToNext[coarse] & fineBit); +} + +void freePage(void *address) {} diff --git a/src/kernel/multiboot/multiboot.c b/src/kernel/multiboot/multiboot.c index f9ce722..794f42c 100644 --- a/src/kernel/multiboot/multiboot.c +++ b/src/kernel/multiboot/multiboot.c @@ -10,7 +10,7 @@ "initrd")) { MultibootModuleTag *module = (void *)tag; uint32_t moduleSize = module->moduleEnd - module->moduleStart; - void *moduleLocation = kernelMapMultiplePhysicalPages( + void *moduleLocation = kernelMapPhysicalCount( PTR(module->moduleStart), PAGE_COUNT(moduleSize)); *fileSize = moduleSize; return moduleLocation; diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c index a61ff1d..db0251e 100644 --- a/src/kernel/service/services.c +++ b/src/kernel/service/services.c @@ -12,6 +12,9 @@ Syscall *currentSyscall; void resume(Syscall *syscall) { + if (U32(syscall) < 0x1000) { + asm("hlt" ::"a"(syscall)); + } currentSyscall = syscall; runFunction(); } @@ -27,9 +30,7 @@ service->pagingInfo.pageDirectory = malloc(0x1000); service->name = serviceName; // todo: make this unwritable! - // todo: use functionsStart as the reference - sharePage(&(service->pagingInfo), PTR(0xFFC02000), - PTR(0xFFC02000)); // functionsStart, functionsStart); + sharePage(&(service->pagingInfo), &functionsStart, &functionsStart); for (uint32_t i = 0; i < header->programHeaderEntryCount; i++) { for (uint32_t page = 0; page < programHeader->segmentMemorySize; page += 0x1000) { diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index 76d1d07..21ef2fe 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -24,12 +24,6 @@ uint32_t parameter1, uint32_t parameter2, uint32_t parameter3) { if (!function) { - if (n++ == 5) { - asm("nop" ::"a"(function), "b"(currentSyscall), - "c"(currentSyscall->respondingTo)); - while (1) - ; - } if (currentSyscall->respondingTo) { listAdd(&callsToProcess, currentSyscall->respondingTo); } @@ -44,7 +38,8 @@ call->service = currentSyscall->service; call->esp = esp; call->respondingTo = currentSyscall->respondingTo; - if (call->respondingTo->service == currentSyscall->service) { + if (call->respondingTo && + call->respondingTo->service == currentSyscall->service) { asm("nop" ::"a"(currentSyscall), "b"(call), "c"(currentSyscall->respondingTo), "d"(0xB105F00D)); while (1) diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index 2ab0784..60d8c0e 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -19,28 +19,34 @@ PageDirectoryEntry *pageDirectory; uint32_t isPageTableInUse[0x20]; uint32_t isPageAllocated[0x8000]; + uint32_t isPageConnectedToNext[0x8000]; uint32_t isPageAllocatedCoarse[0x400]; uint32_t pageSearchStart; } PagingInfo; extern void setupMemory(); extern void reservePagesUntilPhysical(uint32_t endPageId); + extern void memset(void *target, uint8_t byte, uint32_t size); -extern void *kernelMapPhysical(void *address); -extern void *kernelMapMultiplePhysicalPages(void *address, uint32_t size); + extern void *findTarFile(void *fileStart, uint32_t fileSize, char *filename); -extern void *mapPageForNewService(PagingInfo *info, void *virtualTarget); -extern void *malloc(uint32_t size); -extern void free(void *address); + +extern void *kernelMapPhysical(void *address); +extern void *kernelMapPhysicalCount(void *address, uint32_t size); extern void *getPage(); -extern void sharePage(PagingInfo *destination, void *sourceAddress, - void *destinationAddress); +extern void *sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress); +extern void freePage(void *pageAddress); +extern void unmapPage(void *pageAddress); + +extern void free(void *address); +extern void *malloc(uint32_t size); extern void *getPhysicalAddressKernel(void *address); extern void *getPhysicalAddress(PageDirectoryEntry *pageDirectory, void *address); extern uint32_t findPage(PagingInfo *info); extern void *mapTemporary(void *address); -extern void *getMultiplePages(uint32_t size); +extern void *getPagesCount(uint32_t size); #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 33b9b77..f8b6f03 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -37,7 +37,7 @@ } void loadAndScheduleLoader(void *multibootInfo) { - void *address = kernelMapMultiplePhysicalPages(multibootInfo, 4); + void *address = kernelMapPhysicalCount(multibootInfo, 4); initrd = findInitrd(address, &initrdSize); loadInitrdProgram("loader", NULL); } diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c index c6aa5f9..1c63546 100644 --- a/src/kernel/memory/malloc.c +++ b/src/kernel/memory/malloc.c @@ -23,7 +23,7 @@ void *malloc(uint32_t size) { uint32_t sizeBit = LOG2(size) + 1; if (sizeBit > 10) { - return getMultiplePages(((size - 1) >> 12) + 1); + return getPagesCount(((size - 1) >> 12) + 1); } AllocationBlock *block = allocationData[sizeBit], *last = 0; while (1) { @@ -60,7 +60,7 @@ void free(void *location) { AllocationBlock *block = (void *)((uintptr_t)location & ~0xFFF); if (block->magic != ALLOCATION_MAGIC) { - // freePage(location); + freePage(location); return; } uint16_t index = (uint16_t)((uintptr_t)location & 0xFFF) / block->blockSize; diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index 9e528bd..9dca1f3 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -2,6 +2,10 @@ #include #include +#define ADDRESS(pageId) PTR((pageId) << 12) +#define PAGE_ID(address) (U32(address) >> 12) +#define PAGE_OFFSET(address) (U32(address) & 0xFFF) + PageTableEntry *kernelCodePageTable, *kernelDataPageTable; PagingInfo *kernelPhysicalPages, *kernelVirtualPages; @@ -29,18 +33,18 @@ } void *mapTemporary(void *physical) { - kernelDataPageTable[3].targetAddress = U32(physical) >> 12; + kernelDataPageTable[3].targetAddress = PAGE_ID(physical); kernelDataPageTable[3].writable = 1; kernelDataPageTable[3].present = 1; invalidatePage(0xFF803); - return temporaryPage + (U32(physical) & 0xFFF); + return temporaryPage + PAGE_OFFSET(physical); } void *getPhysicalAddress(PageDirectoryEntry *pageDirectory, void *address) { VirtualAddress *virtual = (void *)&address; uint32_t pageTableId = pageDirectory[virtual->pageDirectoryIndex].pageTableID; - PageTableEntry *pageTable = mapTemporary(PTR(pageTableId << 12)); + PageTableEntry *pageTable = mapTemporary(ADDRESS(pageTableId)); uint32_t pageBase = pageTable[virtual->pageTableIndex].targetAddress; return PTR(pageBase << 12 | virtual->pageOffset); } @@ -49,6 +53,21 @@ return getPhysicalAddress(kernelVirtualPages->pageDirectory, address); } +void reservePage(PagingInfo *info, uint32_t pageId) { + uint32_t coarsePosition = pageId / 32; + info->isPageAllocated[coarsePosition] |= 1 << (pageId % 32); + if (info->isPageAllocated[coarsePosition] == ~0) { + info->isPageAllocatedCoarse[coarsePosition / 32] |= + 1 << (coarsePosition % 32); + } +} + +void reservePagesCount(PagingInfo *info, uint32_t startPageId, uint32_t count) { + for (uint32_t i = 0; i < count; i++) { + reservePage(info, startPageId + i); + } +} + void mapPage(PagingInfo *info, void *physical, void *virtual, bool userPage); void reservePagesUntilPhysical(uint32_t endPageId) { @@ -67,26 +86,14 @@ kernelVirtualPages = buffer; buffer += sizeof(PagingInfo); memset(kernelPhysicalPages, 0, 2 * sizeof(PagingInfo)); - for (uint32_t i = 0; i < endPageId; i++) { - reservePage(kernelPhysicalPages, i); - } - for (uint32_t i = 0; i < 0x800; i++) { - reservePage(kernelVirtualPages, i + 0xFF800); - } + reservePagesCount(kernelVirtualPages, 0, 1); + reservePagesCount(kernelPhysicalPages, 0, endPageId); + reservePagesCount(kernelVirtualPages, 0xFF800, 0x800); kernelPhysicalPages->pageSearchStart = endPageId; kernelVirtualPages->pageSearchStart = 0; kernelVirtualPages->pageDirectory = pageDirectory; } -void reservePage(PagingInfo *info, uint32_t pageId) { - uint32_t coarsePosition = pageId / 32; - info->isPageAllocated[coarsePosition] |= 1 << (pageId % 32); - if (info->isPageAllocated[coarsePosition] == ~0) { - info->isPageAllocatedCoarse[coarsePosition / 32] |= - 1 << (coarsePosition % 32); - } -} - uint32_t findMultiplePages(PagingInfo *info, uint32_t size) { for (uint32_t veryCoarse = info->pageSearchStart / 1024;; veryCoarse++) { if (info->isPageAllocatedCoarse[veryCoarse] == ~0) { @@ -118,28 +125,26 @@ uint32_t findPage(PagingInfo *info) { return findMultiplePages(info, 1); } -void *kernelMapMultiplePhysicalPages(void *address, uint32_t size) { - uint32_t physicalPageStart = U32(address) >> 12; +void *kernelMapPhysicalCount(void *address, uint32_t size) { + uint32_t physicalPageStart = PAGE_ID(address); + reservePagesCount(kernelPhysicalPages, physicalPageStart, size); uint32_t virtualPageStart = findMultiplePages(kernelVirtualPages, size); + reservePagesCount(kernelVirtualPages, virtualPageStart, size); for (uint32_t i = 0; i < size; i++) { - reservePage(kernelPhysicalPages, physicalPageStart + i); - reservePage(kernelVirtualPages, virtualPageStart + i); + mapPage(kernelVirtualPages, ADDRESS(physicalPageStart + i), + ADDRESS(virtualPageStart + i), false); } - for (uint32_t i = 0; i < size; i++) { - mapPage(kernelVirtualPages, PTR((physicalPageStart + i) << 12), - PTR((virtualPageStart + i) << 12), false); - } - return PTR((virtualPageStart << 12) + (U32(address) & 0xFFF)); + return ADDRESS(virtualPageStart) + PAGE_OFFSET(address); } void *kernelMapPhysical(void *address) { - uint32_t physicalPageId = U32(address) >> 12; + uint32_t physicalPageId = PAGE_ID(address); reservePage(kernelPhysicalPages, physicalPageId); uint32_t virtualPageId = findPage(kernelVirtualPages); reservePage(kernelVirtualPages, virtualPageId); - mapPage(kernelVirtualPages, PTR(physicalPageId << 12), - PTR(virtualPageId << 12), false); - return PTR((virtualPageId << 12) + (U32(address) & 0xFFF)); + mapPage(kernelVirtualPages, ADDRESS(physicalPageId), ADDRESS(virtualPageId), + false); + return ADDRESS(virtualPageId) + PAGE_OFFSET(address); } void mapPage(PagingInfo *info, void *physical, void *virtual, bool userPage) { @@ -148,7 +153,7 @@ if (!directory[address->pageDirectoryIndex].present) { uint32_t newPageTable = findPage(kernelPhysicalPages); reservePage(kernelPhysicalPages, newPageTable); - void *temporary = mapTemporary(PTR(newPageTable << 12)); + void *temporary = mapTemporary(ADDRESS(newPageTable)); memset(temporary, 0, 0x1000); directory[address->pageDirectoryIndex].pageTableID = newPageTable; directory[address->pageDirectoryIndex].present = 1; @@ -156,14 +161,14 @@ directory[address->pageDirectoryIndex].belongsToUserProcess |= userPage; } void *pageTablePhysical = - PTR(directory[address->pageDirectoryIndex].pageTableID << 12); + ADDRESS(directory[address->pageDirectoryIndex].pageTableID); void *temporary = mapTemporary(pageTablePhysical); PageTableEntry *pageTable = temporary; - pageTable[address->pageTableIndex].targetAddress = U32(physical) >> 12; + pageTable[address->pageTableIndex].targetAddress = PAGE_ID(physical); pageTable[address->pageTableIndex].present = 1; pageTable[address->pageTableIndex].writable = 1; pageTable[address->pageTableIndex].belongsToUserProcess = userPage; - invalidatePage(U32(virtual) >> 12); + invalidatePage(PAGE_ID(virtual)); } void *getPage() { @@ -171,26 +176,85 @@ reservePage(kernelPhysicalPages, physical); uint32_t virtual = findPage(kernelVirtualPages); reservePage(kernelVirtualPages, virtual); - mapPage(kernelVirtualPages, PTR(physical << 12), PTR(virtual << 12), false); - return PTR(virtual << 12); + mapPage(kernelVirtualPages, ADDRESS(physical), ADDRESS(virtual), false); + return ADDRESS(virtual); } -void *getMultiplePages(uint32_t count) { - uint32_t virtual = findMultiplePages(kernelVirtualPages, count); +void *getPagesCount(uint32_t count) { + uint32_t virtualPageId = findMultiplePages(kernelVirtualPages, count); + reservePagesCount(kernelVirtualPages, virtualPageId, count); for (uint32_t i = 0; i < count; i++) { - reservePage(kernelVirtualPages, virtual + i); uint32_t physical = findPage(kernelPhysicalPages); reservePage(kernelPhysicalPages, physical); - mapPage(kernelVirtualPages, PTR(physical << 12), - PTR((virtual + i) << 12), false); + mapPage(kernelVirtualPages, ADDRESS(physical), + ADDRESS(virtualPageId + i), false); } - return PTR(virtual << 12); + return ADDRESS(virtualPageId); } -void sharePage(PagingInfo *destination, void *sourceAddress, - void *destinationAddress) { +void *sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress) { PagingInfo *sourcePagingInfo = kernelVirtualPages; void *physicalSource = getPhysicalAddress(sourcePagingInfo->pageDirectory, sourceAddress); + if (!destinationAddress) { + void *target = ADDRESS(findPage(destination)); + mapPage(destination, physicalSource, target, true); + return target + PAGE_OFFSET(sourceAddress); + } mapPage(destination, physicalSource, destinationAddress, true); + return destinationAddress; } + +void unmapSinglePageFrom(PagingInfo *info, void *pageAddress) { + VirtualAddress *address = (void *)&pageAddress; + PageDirectoryEntry *directory = info->pageDirectory; + void *pageTablePhysical = + ADDRESS(directory[address->pageDirectoryIndex].pageTableID); + void *temporary = mapTemporary(pageTablePhysical); + PageTableEntry *pageTable = temporary; + pageTable[address->pageTableIndex].targetAddress = 0; + pageTable[address->pageTableIndex].present = 0; + invalidatePage(PAGE_ID(pageAddress)); +} + +void markPageFree(PagingInfo *info, uint32_t coarse, uint32_t fine, + uint32_t fineBit) { + info->isPageAllocated[coarse] &= ~fineBit; + info->isPageConnectedToNext[coarse] &= ~fineBit; + info->isPageAllocatedCoarse[coarse / 32] &= ~(1 << (coarse % 32)); +} + +void unmapPageFrom(PagingInfo *info, void *address) { + uint32_t pageId = PAGE_ID(address), coarse, fine, fineBit; + do { + coarse = pageId / 32; + fine = pageId % 32; + fineBit = 1 << fine; + markPageFree(info, coarse, fine, fineBit); + unmapSinglePageFrom(info, ADDRESS(pageId)); + } while (info->isPageConnectedToNext[coarse] & fineBit); +} + +void unmapPage(void *pageAddress) { + unmapPageFrom(kernelVirtualPages, pageAddress); +} + +void freePageFrom(PagingInfo *info, void *address) { + uint32_t pageId = PAGE_ID(address), coarse, fine, fineBit; + do { + coarse = pageId / 32; + fine = pageId % 32; + fineBit = 1 << fine; + markPageFree(info, coarse, fine, fineBit); + PageTableEntry *pageTable = mapTemporary( + ADDRESS(info->pageDirectory[PAGE_ID(pageId)].pageTableID)); + uint32_t physicalPageId = pageTable[PAGE_OFFSET(pageId)].targetAddress; + uint32_t physicalFine = physicalPageId % 32; + markPageFree(kernelPhysicalPages, physicalPageId / 32, physicalFine, + 1 << physicalFine); + unmapSinglePageFrom(info, ADDRESS(pageId)); + } while (info->isPageConnectedToNext[coarse] & fineBit); +} + +void freePage(void *address) {} diff --git a/src/kernel/multiboot/multiboot.c b/src/kernel/multiboot/multiboot.c index f9ce722..794f42c 100644 --- a/src/kernel/multiboot/multiboot.c +++ b/src/kernel/multiboot/multiboot.c @@ -10,7 +10,7 @@ "initrd")) { MultibootModuleTag *module = (void *)tag; uint32_t moduleSize = module->moduleEnd - module->moduleStart; - void *moduleLocation = kernelMapMultiplePhysicalPages( + void *moduleLocation = kernelMapPhysicalCount( PTR(module->moduleStart), PAGE_COUNT(moduleSize)); *fileSize = moduleSize; return moduleLocation; diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c index a61ff1d..db0251e 100644 --- a/src/kernel/service/services.c +++ b/src/kernel/service/services.c @@ -12,6 +12,9 @@ Syscall *currentSyscall; void resume(Syscall *syscall) { + if (U32(syscall) < 0x1000) { + asm("hlt" ::"a"(syscall)); + } currentSyscall = syscall; runFunction(); } @@ -27,9 +30,7 @@ service->pagingInfo.pageDirectory = malloc(0x1000); service->name = serviceName; // todo: make this unwritable! - // todo: use functionsStart as the reference - sharePage(&(service->pagingInfo), PTR(0xFFC02000), - PTR(0xFFC02000)); // functionsStart, functionsStart); + sharePage(&(service->pagingInfo), &functionsStart, &functionsStart); for (uint32_t i = 0; i < header->programHeaderEntryCount; i++) { for (uint32_t page = 0; page < programHeader->segmentMemorySize; page += 0x1000) { diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index 76d1d07..21ef2fe 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -24,12 +24,6 @@ uint32_t parameter1, uint32_t parameter2, uint32_t parameter3) { if (!function) { - if (n++ == 5) { - asm("nop" ::"a"(function), "b"(currentSyscall), - "c"(currentSyscall->respondingTo)); - while (1) - ; - } if (currentSyscall->respondingTo) { listAdd(&callsToProcess, currentSyscall->respondingTo); } @@ -44,7 +38,8 @@ call->service = currentSyscall->service; call->esp = esp; call->respondingTo = currentSyscall->respondingTo; - if (call->respondingTo->service == currentSyscall->service) { + if (call->respondingTo && + call->respondingTo->service == currentSyscall->service) { asm("nop" ::"a"(currentSyscall), "b"(call), "c"(currentSyscall->respondingTo), "d"(0xB105F00D)); while (1) diff --git a/src/userland/log/Makefile b/src/userland/log/Makefile index f8624c6..5b974b2 100644 --- a/src/userland/log/Makefile +++ b/src/userland/log/Makefile @@ -10,7 +10,7 @@ SOURCE_FILES := $(shell find . -name *.c -or -name *.asm -or -name *.s) OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) -../../../initrd/loader: $(OBJS) +../../../initrd/log: $(OBJS) @echo "linking user program log" @$(LD) $(LD_FLAGS) -o ../../../initrd/log $(OBJS)