diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index cb41d70..5731bda 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -3,11 +3,39 @@ #include +typedef struct { + uint32_t present : 1; + uint32_t writable : 1; + uint32_t belongsToUserProcess : 1; + uint32_t reserved : 2; + uint32_t accessed : 1; + uint32_t dirty : 1; + uint32_t reserved2 : 2; + uint32_t available : 3; + uint32_t pageTableID : 20; +} __attribute__((packed)) PageDirectoryEntry; + +typedef struct { + PageDirectoryEntry *pageDirectory; + uint32_t isPageTableInUse[0x20]; + uint32_t isPageAllocated[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 *getPage(); +extern void sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress); + +extern void *getPhysicalAddressKernel(void *address); #endif diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index cb41d70..5731bda 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -3,11 +3,39 @@ #include +typedef struct { + uint32_t present : 1; + uint32_t writable : 1; + uint32_t belongsToUserProcess : 1; + uint32_t reserved : 2; + uint32_t accessed : 1; + uint32_t dirty : 1; + uint32_t reserved2 : 2; + uint32_t available : 3; + uint32_t pageTableID : 20; +} __attribute__((packed)) PageDirectoryEntry; + +typedef struct { + PageDirectoryEntry *pageDirectory; + uint32_t isPageTableInUse[0x20]; + uint32_t isPageAllocated[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 *getPage(); +extern void sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress); + +extern void *getPhysicalAddressKernel(void *address); #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h new file mode 100644 index 0000000..b746d66 --- /dev/null +++ b/src/kernel/include/service.h @@ -0,0 +1,6 @@ +#ifndef SERVICE_H +#define SERVICE_H + +extern void loadElf(void *fileData); + +#endif diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index cb41d70..5731bda 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -3,11 +3,39 @@ #include +typedef struct { + uint32_t present : 1; + uint32_t writable : 1; + uint32_t belongsToUserProcess : 1; + uint32_t reserved : 2; + uint32_t accessed : 1; + uint32_t dirty : 1; + uint32_t reserved2 : 2; + uint32_t available : 3; + uint32_t pageTableID : 20; +} __attribute__((packed)) PageDirectoryEntry; + +typedef struct { + PageDirectoryEntry *pageDirectory; + uint32_t isPageTableInUse[0x20]; + uint32_t isPageAllocated[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 *getPage(); +extern void sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress); + +extern void *getPhysicalAddressKernel(void *address); #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h new file mode 100644 index 0000000..b746d66 --- /dev/null +++ b/src/kernel/include/service.h @@ -0,0 +1,6 @@ +#ifndef SERVICE_H +#define SERVICE_H + +extern void loadElf(void *fileData); + +#endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index ac89942..748a044 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -2,14 +2,18 @@ #define UTIL_H #include +#include #define U32(x) (uint32_t)(uintptr_t)(x) #define PTR(x) (void *)(uintptr_t)(x) #define NULL PTR(0) +#define MIN(x, y) (x < y ? x : y) + #define PAGE_COUNT(x) (((x - 1) / 4096) + 1) extern bool stringEquals(char *string1, char *string2); +extern void memcpy(void *source, void *destination, uint32_t size); #endif diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index cb41d70..5731bda 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -3,11 +3,39 @@ #include +typedef struct { + uint32_t present : 1; + uint32_t writable : 1; + uint32_t belongsToUserProcess : 1; + uint32_t reserved : 2; + uint32_t accessed : 1; + uint32_t dirty : 1; + uint32_t reserved2 : 2; + uint32_t available : 3; + uint32_t pageTableID : 20; +} __attribute__((packed)) PageDirectoryEntry; + +typedef struct { + PageDirectoryEntry *pageDirectory; + uint32_t isPageTableInUse[0x20]; + uint32_t isPageAllocated[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 *getPage(); +extern void sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress); + +extern void *getPhysicalAddressKernel(void *address); #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h new file mode 100644 index 0000000..b746d66 --- /dev/null +++ b/src/kernel/include/service.h @@ -0,0 +1,6 @@ +#ifndef SERVICE_H +#define SERVICE_H + +extern void loadElf(void *fileData); + +#endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index ac89942..748a044 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -2,14 +2,18 @@ #define UTIL_H #include +#include #define U32(x) (uint32_t)(uintptr_t)(x) #define PTR(x) (void *)(uintptr_t)(x) #define NULL PTR(0) +#define MIN(x, y) (x < y ? x : y) + #define PAGE_COUNT(x) (((x - 1) / 4096) + 1) extern bool stringEquals(char *string1, char *string2); +extern void memcpy(void *source, void *destination, uint32_t size); #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 7fdcc82..9b91775 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -1,13 +1,15 @@ #include #include +#include #include void kernelMain(void *multibootInfo) { setupMemory(); - void *address = kernelMapPhysical(multibootInfo); + void *address = kernelMapMultiplePhysicalPages(multibootInfo, 4); uint32_t tarSize = 0; void *initrd = findInitrd(address, &tarSize); void *loaderProgram = findTarFile(initrd, tarSize, "initrd/loader"); + loadElf(loaderProgram); asm("mov %%eax, %0" ::"r"(loaderProgram)); while (1) ; diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index cb41d70..5731bda 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -3,11 +3,39 @@ #include +typedef struct { + uint32_t present : 1; + uint32_t writable : 1; + uint32_t belongsToUserProcess : 1; + uint32_t reserved : 2; + uint32_t accessed : 1; + uint32_t dirty : 1; + uint32_t reserved2 : 2; + uint32_t available : 3; + uint32_t pageTableID : 20; +} __attribute__((packed)) PageDirectoryEntry; + +typedef struct { + PageDirectoryEntry *pageDirectory; + uint32_t isPageTableInUse[0x20]; + uint32_t isPageAllocated[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 *getPage(); +extern void sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress); + +extern void *getPhysicalAddressKernel(void *address); #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h new file mode 100644 index 0000000..b746d66 --- /dev/null +++ b/src/kernel/include/service.h @@ -0,0 +1,6 @@ +#ifndef SERVICE_H +#define SERVICE_H + +extern void loadElf(void *fileData); + +#endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index ac89942..748a044 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -2,14 +2,18 @@ #define UTIL_H #include +#include #define U32(x) (uint32_t)(uintptr_t)(x) #define PTR(x) (void *)(uintptr_t)(x) #define NULL PTR(0) +#define MIN(x, y) (x < y ? x : y) + #define PAGE_COUNT(x) (((x - 1) / 4096) + 1) extern bool stringEquals(char *string1, char *string2); +extern void memcpy(void *source, void *destination, uint32_t size); #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 7fdcc82..9b91775 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -1,13 +1,15 @@ #include #include +#include #include void kernelMain(void *multibootInfo) { setupMemory(); - void *address = kernelMapPhysical(multibootInfo); + void *address = kernelMapMultiplePhysicalPages(multibootInfo, 4); uint32_t tarSize = 0; void *initrd = findInitrd(address, &tarSize); void *loaderProgram = findTarFile(initrd, tarSize, "initrd/loader"); + loadElf(loaderProgram); asm("mov %%eax, %0" ::"r"(loaderProgram)); while (1) ; diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c new file mode 100644 index 0000000..b6b9b40 --- /dev/null +++ b/src/kernel/memory/malloc.c @@ -0,0 +1,76 @@ +#include "malloc.h" +#include + +#define LOG2(X) ((unsigned)(64 - __builtin_clzll((X)) - 1)) + +AllocationData allocationData; + +void *reserveBlock(AllocationBlock *block, uint8_t coarse, uint8_t fine) { + block->allocatedFine[coarse] |= 1 << fine; + block->allocatedCoarse |= 1 << coarse; + for (uint8_t i = 0; i < 32; i++) { + if (block->allocatedFine[coarse] & 1 << i) { + continue; + } + block->allocatedCoarse &= ~(1 << coarse); + break; + } + return ((uint8_t *)block) + block->blockSize * (32 * coarse + fine); +} + +void *malloc(uint32_t size) { + uint32_t sizeBit = LOG2(size) + 1; + if (sizeBit > 10) { + return getPage(); + } + AllocationBlock *block = allocationData[sizeBit], *last = 0; + while (1) { + if (!block) { + block = getPage(); + memset(block, 0, 4096); + block->blockSize = 1 << sizeBit; + if (last) { + block->previous = last; + last->next = block; + } else { + allocationData[sizeBit] = block; + block->previous = (void *)(uintptr_t)sizeBit; + } + block->magic = ALLOCATION_MAGIC; + } + if (block->allocatedCoarse == ~0) { + goto end; + } + for (uint8_t coarse = 0; coarse < 32; coarse++) { + for (uint8_t fine = 0; fine < 32; fine++) { + if (block->allocatedFine[coarse] & (1 << fine)) { + continue; + } + return reserveBlock(block, coarse, fine); + } + } + end: + last = block; + block = block->next; + } +} + +void free(void *location) { + AllocationBlock *block = (void *)((uintptr_t)location & ~0xFFF); + if (block->magic != ALLOCATION_MAGIC) { + // freePage(location); + return; + } + uint16_t index = (uint16_t)((uintptr_t)location & 0xFFF) / block->blockSize; + uint8_t coarse = index / 32; + uint8_t fine = index % 32; + block->allocatedFine[coarse] &= ~(1 << fine); + block->allocatedCoarse &= ~(1 << coarse); + for (uint8_t i = 0; i < 32; i++) { + if (block->allocatedFine[coarse] & (1 << i)) { + continue; + } + block->allocatedCoarse |= 1 << coarse; + return; + } +} diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index cb41d70..5731bda 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -3,11 +3,39 @@ #include +typedef struct { + uint32_t present : 1; + uint32_t writable : 1; + uint32_t belongsToUserProcess : 1; + uint32_t reserved : 2; + uint32_t accessed : 1; + uint32_t dirty : 1; + uint32_t reserved2 : 2; + uint32_t available : 3; + uint32_t pageTableID : 20; +} __attribute__((packed)) PageDirectoryEntry; + +typedef struct { + PageDirectoryEntry *pageDirectory; + uint32_t isPageTableInUse[0x20]; + uint32_t isPageAllocated[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 *getPage(); +extern void sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress); + +extern void *getPhysicalAddressKernel(void *address); #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h new file mode 100644 index 0000000..b746d66 --- /dev/null +++ b/src/kernel/include/service.h @@ -0,0 +1,6 @@ +#ifndef SERVICE_H +#define SERVICE_H + +extern void loadElf(void *fileData); + +#endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index ac89942..748a044 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -2,14 +2,18 @@ #define UTIL_H #include +#include #define U32(x) (uint32_t)(uintptr_t)(x) #define PTR(x) (void *)(uintptr_t)(x) #define NULL PTR(0) +#define MIN(x, y) (x < y ? x : y) + #define PAGE_COUNT(x) (((x - 1) / 4096) + 1) extern bool stringEquals(char *string1, char *string2); +extern void memcpy(void *source, void *destination, uint32_t size); #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 7fdcc82..9b91775 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -1,13 +1,15 @@ #include #include +#include #include void kernelMain(void *multibootInfo) { setupMemory(); - void *address = kernelMapPhysical(multibootInfo); + void *address = kernelMapMultiplePhysicalPages(multibootInfo, 4); uint32_t tarSize = 0; void *initrd = findInitrd(address, &tarSize); void *loaderProgram = findTarFile(initrd, tarSize, "initrd/loader"); + loadElf(loaderProgram); asm("mov %%eax, %0" ::"r"(loaderProgram)); while (1) ; diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c new file mode 100644 index 0000000..b6b9b40 --- /dev/null +++ b/src/kernel/memory/malloc.c @@ -0,0 +1,76 @@ +#include "malloc.h" +#include + +#define LOG2(X) ((unsigned)(64 - __builtin_clzll((X)) - 1)) + +AllocationData allocationData; + +void *reserveBlock(AllocationBlock *block, uint8_t coarse, uint8_t fine) { + block->allocatedFine[coarse] |= 1 << fine; + block->allocatedCoarse |= 1 << coarse; + for (uint8_t i = 0; i < 32; i++) { + if (block->allocatedFine[coarse] & 1 << i) { + continue; + } + block->allocatedCoarse &= ~(1 << coarse); + break; + } + return ((uint8_t *)block) + block->blockSize * (32 * coarse + fine); +} + +void *malloc(uint32_t size) { + uint32_t sizeBit = LOG2(size) + 1; + if (sizeBit > 10) { + return getPage(); + } + AllocationBlock *block = allocationData[sizeBit], *last = 0; + while (1) { + if (!block) { + block = getPage(); + memset(block, 0, 4096); + block->blockSize = 1 << sizeBit; + if (last) { + block->previous = last; + last->next = block; + } else { + allocationData[sizeBit] = block; + block->previous = (void *)(uintptr_t)sizeBit; + } + block->magic = ALLOCATION_MAGIC; + } + if (block->allocatedCoarse == ~0) { + goto end; + } + for (uint8_t coarse = 0; coarse < 32; coarse++) { + for (uint8_t fine = 0; fine < 32; fine++) { + if (block->allocatedFine[coarse] & (1 << fine)) { + continue; + } + return reserveBlock(block, coarse, fine); + } + } + end: + last = block; + block = block->next; + } +} + +void free(void *location) { + AllocationBlock *block = (void *)((uintptr_t)location & ~0xFFF); + if (block->magic != ALLOCATION_MAGIC) { + // freePage(location); + return; + } + uint16_t index = (uint16_t)((uintptr_t)location & 0xFFF) / block->blockSize; + uint8_t coarse = index / 32; + uint8_t fine = index % 32; + block->allocatedFine[coarse] &= ~(1 << fine); + block->allocatedCoarse &= ~(1 << coarse); + for (uint8_t i = 0; i < 32; i++) { + if (block->allocatedFine[coarse] & (1 << i)) { + continue; + } + block->allocatedCoarse |= 1 << coarse; + return; + } +} diff --git a/src/kernel/memory/malloc.h b/src/kernel/memory/malloc.h new file mode 100644 index 0000000..16e0c80 --- /dev/null +++ b/src/kernel/memory/malloc.h @@ -0,0 +1,20 @@ +#ifndef ALLOC_H +#define ALLOC_H + +#include + +#define ALLOCATION_MAGIC 0x44BB33DD + +typedef struct AllocationBlock { + uint8_t data[3948]; + uint32_t allocatedFine[32]; + uint32_t allocatedCoarse; + uint32_t blockSize; + struct AllocationBlock *next; + struct AllocationBlock *previous; + uint32_t magic; +} AllocationBlock; + +typedef AllocationBlock *AllocationData[12]; + +#endif diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index cb41d70..5731bda 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -3,11 +3,39 @@ #include +typedef struct { + uint32_t present : 1; + uint32_t writable : 1; + uint32_t belongsToUserProcess : 1; + uint32_t reserved : 2; + uint32_t accessed : 1; + uint32_t dirty : 1; + uint32_t reserved2 : 2; + uint32_t available : 3; + uint32_t pageTableID : 20; +} __attribute__((packed)) PageDirectoryEntry; + +typedef struct { + PageDirectoryEntry *pageDirectory; + uint32_t isPageTableInUse[0x20]; + uint32_t isPageAllocated[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 *getPage(); +extern void sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress); + +extern void *getPhysicalAddressKernel(void *address); #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h new file mode 100644 index 0000000..b746d66 --- /dev/null +++ b/src/kernel/include/service.h @@ -0,0 +1,6 @@ +#ifndef SERVICE_H +#define SERVICE_H + +extern void loadElf(void *fileData); + +#endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index ac89942..748a044 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -2,14 +2,18 @@ #define UTIL_H #include +#include #define U32(x) (uint32_t)(uintptr_t)(x) #define PTR(x) (void *)(uintptr_t)(x) #define NULL PTR(0) +#define MIN(x, y) (x < y ? x : y) + #define PAGE_COUNT(x) (((x - 1) / 4096) + 1) extern bool stringEquals(char *string1, char *string2); +extern void memcpy(void *source, void *destination, uint32_t size); #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 7fdcc82..9b91775 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -1,13 +1,15 @@ #include #include +#include #include void kernelMain(void *multibootInfo) { setupMemory(); - void *address = kernelMapPhysical(multibootInfo); + void *address = kernelMapMultiplePhysicalPages(multibootInfo, 4); uint32_t tarSize = 0; void *initrd = findInitrd(address, &tarSize); void *loaderProgram = findTarFile(initrd, tarSize, "initrd/loader"); + loadElf(loaderProgram); asm("mov %%eax, %0" ::"r"(loaderProgram)); while (1) ; diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c new file mode 100644 index 0000000..b6b9b40 --- /dev/null +++ b/src/kernel/memory/malloc.c @@ -0,0 +1,76 @@ +#include "malloc.h" +#include + +#define LOG2(X) ((unsigned)(64 - __builtin_clzll((X)) - 1)) + +AllocationData allocationData; + +void *reserveBlock(AllocationBlock *block, uint8_t coarse, uint8_t fine) { + block->allocatedFine[coarse] |= 1 << fine; + block->allocatedCoarse |= 1 << coarse; + for (uint8_t i = 0; i < 32; i++) { + if (block->allocatedFine[coarse] & 1 << i) { + continue; + } + block->allocatedCoarse &= ~(1 << coarse); + break; + } + return ((uint8_t *)block) + block->blockSize * (32 * coarse + fine); +} + +void *malloc(uint32_t size) { + uint32_t sizeBit = LOG2(size) + 1; + if (sizeBit > 10) { + return getPage(); + } + AllocationBlock *block = allocationData[sizeBit], *last = 0; + while (1) { + if (!block) { + block = getPage(); + memset(block, 0, 4096); + block->blockSize = 1 << sizeBit; + if (last) { + block->previous = last; + last->next = block; + } else { + allocationData[sizeBit] = block; + block->previous = (void *)(uintptr_t)sizeBit; + } + block->magic = ALLOCATION_MAGIC; + } + if (block->allocatedCoarse == ~0) { + goto end; + } + for (uint8_t coarse = 0; coarse < 32; coarse++) { + for (uint8_t fine = 0; fine < 32; fine++) { + if (block->allocatedFine[coarse] & (1 << fine)) { + continue; + } + return reserveBlock(block, coarse, fine); + } + } + end: + last = block; + block = block->next; + } +} + +void free(void *location) { + AllocationBlock *block = (void *)((uintptr_t)location & ~0xFFF); + if (block->magic != ALLOCATION_MAGIC) { + // freePage(location); + return; + } + uint16_t index = (uint16_t)((uintptr_t)location & 0xFFF) / block->blockSize; + uint8_t coarse = index / 32; + uint8_t fine = index % 32; + block->allocatedFine[coarse] &= ~(1 << fine); + block->allocatedCoarse &= ~(1 << coarse); + for (uint8_t i = 0; i < 32; i++) { + if (block->allocatedFine[coarse] & (1 << i)) { + continue; + } + block->allocatedCoarse |= 1 << coarse; + return; + } +} diff --git a/src/kernel/memory/malloc.h b/src/kernel/memory/malloc.h new file mode 100644 index 0000000..16e0c80 --- /dev/null +++ b/src/kernel/memory/malloc.h @@ -0,0 +1,20 @@ +#ifndef ALLOC_H +#define ALLOC_H + +#include + +#define ALLOCATION_MAGIC 0x44BB33DD + +typedef struct AllocationBlock { + uint8_t data[3948]; + uint32_t allocatedFine[32]; + uint32_t allocatedCoarse; + uint32_t blockSize; + struct AllocationBlock *next; + struct AllocationBlock *previous; + uint32_t magic; +} AllocationBlock; + +typedef AllocationBlock *AllocationData[12]; + +#endif diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index 0213f25..3bd35e9 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -2,13 +2,18 @@ #include #include -PageDirectoryEntry *kernelDirectory; -PageTableEntry *kernelCodePageTable, *kernelDataPageTable, *kernelUtilityPages; +PageTableEntry *kernelCodePageTable, *kernelDataPageTable; -PagingInfo *physicalPages, *kernelVirtualPages; +PagingInfo *kernelPhysicalPages, *kernelVirtualPages; + +void *temporaryPage; void reservePage(PagingInfo *info, uint32_t pageId); +void invalidatePage(uint32_t pageId) { + asm("invlpg (%0)" ::"r"(pageId << 12) : "memory"); +} + void *kernelGetVirtualAddress(void *_address) { uint32_t address = (uint32_t)(uintptr_t)_address; if (address < 0x100000) { @@ -23,52 +28,56 @@ return 0; } +void *mapTemporary(void *physical) { + kernelDataPageTable[3].targetAddress = U32(physical) >> 12; + kernelDataPageTable[3].writable = 1; + kernelDataPageTable[3].present = 1; + invalidatePage(0xFF803); + return temporaryPage; +} + void *getPhysicalAddress(void *address, PageDirectoryEntry *pageDirectory) { VirtualAddress *virtual = (void *)&address; uint32_t pageTableLocation = pageDirectory[virtual->pageDirectoryIndex].pageTableID; PageTableEntry *pageTable = PTR(pageTableLocation << 12); - pageTable = kernelGetVirtualAddress(pageTable); + pageTable = mapTemporary(pageTable); uint32_t pageBase = pageTable[virtual->pageTableIndex].targetAddress; return PTR(pageBase << 12 | virtual->pageOffset); } -void mapDirectoryEntry(PageDirectoryEntry *directory, uint32_t pageTableIndex, - PageTableEntry *pageTable, PagingInfo *pagingInfo) { - directory[pageTableIndex].pageTableID = - U32(getPhysicalAddress(pageTable, directory)) >> 12; - directory[pageTableIndex].writable = 1; - directory[pageTableIndex].present = 1; - pagingInfo->isPageTableInUse[pageTableIndex / 32] |= - 1 << (pageTableIndex % 32); +void *getPhysicalAddressKernel(void *address) { + return getPhysicalAddress(address, kernelVirtualPages->pageDirectory); } +uint32_t findPage(PagingInfo *info); +void mapPage(PagingInfo *info, void *physical, void *virtual); + void reservePagesUntilPhysical(uint32_t endPageId) { void *buffer = (void *)0xFF800000; - kernelDirectory = buffer; - memset(kernelDirectory, 0, 0xFF8); - buffer += 0x1000; - kernelCodePageTable = buffer; + void *pageDirectory = buffer; + memset(pageDirectory, 0, 0xFF8); buffer += 0x1000; kernelDataPageTable = buffer; buffer += 0x1000; - kernelUtilityPages = buffer; + kernelCodePageTable = buffer; buffer += 0x1000; - physicalPages = buffer; + temporaryPage = buffer; + buffer += 0x1000; + kernelPhysicalPages = buffer; buffer += sizeof(PagingInfo); kernelVirtualPages = buffer; buffer += sizeof(PagingInfo); - memset(physicalPages, 0, 2 * sizeof(PagingInfo)); + memset(kernelPhysicalPages, 0, 2 * sizeof(PagingInfo)); for (uint32_t i = 0; i < endPageId; i++) { - reservePage(physicalPages, i); + reservePage(kernelPhysicalPages, i); } for (uint32_t i = 0; i < 0x800; i++) { reservePage(kernelVirtualPages, i + 0xFF800); } - memset(kernelUtilityPages, 0, 0x1000); - mapDirectoryEntry(kernelDirectory, 0, kernelUtilityPages, - kernelVirtualPages); - physicalPages->pageSearchStart = endPageId; + kernelPhysicalPages->pageSearchStart = endPageId; + kernelVirtualPages->pageSearchStart = 0; + kernelVirtualPages->pageDirectory = pageDirectory; } void reservePage(PagingInfo *info, uint32_t pageId) { @@ -115,12 +124,12 @@ uint32_t physicalPageStart = U32(address) >> 12; uint32_t virtualPageStart = findMultiplePages(kernelVirtualPages, size); for (uint32_t i = 0; i < size; i++) { - reservePage(physicalPages, physicalPageStart + i); + reservePage(kernelPhysicalPages, physicalPageStart + i); reservePage(kernelVirtualPages, virtualPageStart + i); - kernelUtilityPages[virtualPageStart + i].targetAddress = - physicalPageStart + i; - kernelUtilityPages[virtualPageStart + i].writable = 1; - kernelUtilityPages[virtualPageStart + i].present = 1; + } + for (uint32_t i = 0; i < size; i++) { + mapPage(kernelVirtualPages, PTR((physicalPageStart + i) << 12), + PTR((virtualPageStart + i) << 12)); } return PTR((virtualPageStart << 12) + (U32(address) & 0xFFF)); } @@ -128,3 +137,42 @@ void *kernelMapPhysical(void *address) { return kernelMapMultiplePhysicalPages(address, 1); } + +void mapPage(PagingInfo *info, void *physical, void *virtual) { + VirtualAddress *address = (void *)&virtual; + PageDirectoryEntry *directory = info->pageDirectory; + if (!directory[address->pageDirectoryIndex].present) { + uint32_t newPageTable = findPage(kernelPhysicalPages); + reservePage(kernelPhysicalPages, newPageTable); + void *temporary = mapTemporary(PTR(newPageTable << 12)); + memset(temporary, 0, 0x1000); + directory[address->pageDirectoryIndex].pageTableID = newPageTable; + directory[address->pageDirectoryIndex].present = 1; + directory[address->pageDirectoryIndex].writable = 1; + } + void *pageTablePhysical = + PTR(directory[address->pageDirectoryIndex].pageTableID << 12); + void *temporary = mapTemporary(pageTablePhysical); + PageTableEntry *pageTable = temporary; + pageTable[address->pageTableIndex].targetAddress = U32(physical) >> 12; + pageTable[address->pageTableIndex].present = 1; + pageTable[address->pageTableIndex].writable = 1; + invalidatePage(U32(virtual) >> 12); +} + +void *getPage() { + uint32_t physical = findPage(kernelPhysicalPages); + reservePage(kernelPhysicalPages, physical); + uint32_t virtual = findPage(kernelVirtualPages); + reservePage(kernelVirtualPages, virtual); + mapPage(kernelVirtualPages, PTR(physical << 12), PTR(virtual << 12)); + return PTR(virtual << 12); +} + +void sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress) { + PagingInfo *source = kernelVirtualPages; + void *physicalSource = + getPhysicalAddress(sourceAddress, source->pageDirectory); + mapPage(destination, physicalSource, destinationAddress); +} diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index cb41d70..5731bda 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -3,11 +3,39 @@ #include +typedef struct { + uint32_t present : 1; + uint32_t writable : 1; + uint32_t belongsToUserProcess : 1; + uint32_t reserved : 2; + uint32_t accessed : 1; + uint32_t dirty : 1; + uint32_t reserved2 : 2; + uint32_t available : 3; + uint32_t pageTableID : 20; +} __attribute__((packed)) PageDirectoryEntry; + +typedef struct { + PageDirectoryEntry *pageDirectory; + uint32_t isPageTableInUse[0x20]; + uint32_t isPageAllocated[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 *getPage(); +extern void sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress); + +extern void *getPhysicalAddressKernel(void *address); #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h new file mode 100644 index 0000000..b746d66 --- /dev/null +++ b/src/kernel/include/service.h @@ -0,0 +1,6 @@ +#ifndef SERVICE_H +#define SERVICE_H + +extern void loadElf(void *fileData); + +#endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index ac89942..748a044 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -2,14 +2,18 @@ #define UTIL_H #include +#include #define U32(x) (uint32_t)(uintptr_t)(x) #define PTR(x) (void *)(uintptr_t)(x) #define NULL PTR(0) +#define MIN(x, y) (x < y ? x : y) + #define PAGE_COUNT(x) (((x - 1) / 4096) + 1) extern bool stringEquals(char *string1, char *string2); +extern void memcpy(void *source, void *destination, uint32_t size); #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 7fdcc82..9b91775 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -1,13 +1,15 @@ #include #include +#include #include void kernelMain(void *multibootInfo) { setupMemory(); - void *address = kernelMapPhysical(multibootInfo); + void *address = kernelMapMultiplePhysicalPages(multibootInfo, 4); uint32_t tarSize = 0; void *initrd = findInitrd(address, &tarSize); void *loaderProgram = findTarFile(initrd, tarSize, "initrd/loader"); + loadElf(loaderProgram); asm("mov %%eax, %0" ::"r"(loaderProgram)); while (1) ; diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c new file mode 100644 index 0000000..b6b9b40 --- /dev/null +++ b/src/kernel/memory/malloc.c @@ -0,0 +1,76 @@ +#include "malloc.h" +#include + +#define LOG2(X) ((unsigned)(64 - __builtin_clzll((X)) - 1)) + +AllocationData allocationData; + +void *reserveBlock(AllocationBlock *block, uint8_t coarse, uint8_t fine) { + block->allocatedFine[coarse] |= 1 << fine; + block->allocatedCoarse |= 1 << coarse; + for (uint8_t i = 0; i < 32; i++) { + if (block->allocatedFine[coarse] & 1 << i) { + continue; + } + block->allocatedCoarse &= ~(1 << coarse); + break; + } + return ((uint8_t *)block) + block->blockSize * (32 * coarse + fine); +} + +void *malloc(uint32_t size) { + uint32_t sizeBit = LOG2(size) + 1; + if (sizeBit > 10) { + return getPage(); + } + AllocationBlock *block = allocationData[sizeBit], *last = 0; + while (1) { + if (!block) { + block = getPage(); + memset(block, 0, 4096); + block->blockSize = 1 << sizeBit; + if (last) { + block->previous = last; + last->next = block; + } else { + allocationData[sizeBit] = block; + block->previous = (void *)(uintptr_t)sizeBit; + } + block->magic = ALLOCATION_MAGIC; + } + if (block->allocatedCoarse == ~0) { + goto end; + } + for (uint8_t coarse = 0; coarse < 32; coarse++) { + for (uint8_t fine = 0; fine < 32; fine++) { + if (block->allocatedFine[coarse] & (1 << fine)) { + continue; + } + return reserveBlock(block, coarse, fine); + } + } + end: + last = block; + block = block->next; + } +} + +void free(void *location) { + AllocationBlock *block = (void *)((uintptr_t)location & ~0xFFF); + if (block->magic != ALLOCATION_MAGIC) { + // freePage(location); + return; + } + uint16_t index = (uint16_t)((uintptr_t)location & 0xFFF) / block->blockSize; + uint8_t coarse = index / 32; + uint8_t fine = index % 32; + block->allocatedFine[coarse] &= ~(1 << fine); + block->allocatedCoarse &= ~(1 << coarse); + for (uint8_t i = 0; i < 32; i++) { + if (block->allocatedFine[coarse] & (1 << i)) { + continue; + } + block->allocatedCoarse |= 1 << coarse; + return; + } +} diff --git a/src/kernel/memory/malloc.h b/src/kernel/memory/malloc.h new file mode 100644 index 0000000..16e0c80 --- /dev/null +++ b/src/kernel/memory/malloc.h @@ -0,0 +1,20 @@ +#ifndef ALLOC_H +#define ALLOC_H + +#include + +#define ALLOCATION_MAGIC 0x44BB33DD + +typedef struct AllocationBlock { + uint8_t data[3948]; + uint32_t allocatedFine[32]; + uint32_t allocatedCoarse; + uint32_t blockSize; + struct AllocationBlock *next; + struct AllocationBlock *previous; + uint32_t magic; +} AllocationBlock; + +typedef AllocationBlock *AllocationData[12]; + +#endif diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index 0213f25..3bd35e9 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -2,13 +2,18 @@ #include #include -PageDirectoryEntry *kernelDirectory; -PageTableEntry *kernelCodePageTable, *kernelDataPageTable, *kernelUtilityPages; +PageTableEntry *kernelCodePageTable, *kernelDataPageTable; -PagingInfo *physicalPages, *kernelVirtualPages; +PagingInfo *kernelPhysicalPages, *kernelVirtualPages; + +void *temporaryPage; void reservePage(PagingInfo *info, uint32_t pageId); +void invalidatePage(uint32_t pageId) { + asm("invlpg (%0)" ::"r"(pageId << 12) : "memory"); +} + void *kernelGetVirtualAddress(void *_address) { uint32_t address = (uint32_t)(uintptr_t)_address; if (address < 0x100000) { @@ -23,52 +28,56 @@ return 0; } +void *mapTemporary(void *physical) { + kernelDataPageTable[3].targetAddress = U32(physical) >> 12; + kernelDataPageTable[3].writable = 1; + kernelDataPageTable[3].present = 1; + invalidatePage(0xFF803); + return temporaryPage; +} + void *getPhysicalAddress(void *address, PageDirectoryEntry *pageDirectory) { VirtualAddress *virtual = (void *)&address; uint32_t pageTableLocation = pageDirectory[virtual->pageDirectoryIndex].pageTableID; PageTableEntry *pageTable = PTR(pageTableLocation << 12); - pageTable = kernelGetVirtualAddress(pageTable); + pageTable = mapTemporary(pageTable); uint32_t pageBase = pageTable[virtual->pageTableIndex].targetAddress; return PTR(pageBase << 12 | virtual->pageOffset); } -void mapDirectoryEntry(PageDirectoryEntry *directory, uint32_t pageTableIndex, - PageTableEntry *pageTable, PagingInfo *pagingInfo) { - directory[pageTableIndex].pageTableID = - U32(getPhysicalAddress(pageTable, directory)) >> 12; - directory[pageTableIndex].writable = 1; - directory[pageTableIndex].present = 1; - pagingInfo->isPageTableInUse[pageTableIndex / 32] |= - 1 << (pageTableIndex % 32); +void *getPhysicalAddressKernel(void *address) { + return getPhysicalAddress(address, kernelVirtualPages->pageDirectory); } +uint32_t findPage(PagingInfo *info); +void mapPage(PagingInfo *info, void *physical, void *virtual); + void reservePagesUntilPhysical(uint32_t endPageId) { void *buffer = (void *)0xFF800000; - kernelDirectory = buffer; - memset(kernelDirectory, 0, 0xFF8); - buffer += 0x1000; - kernelCodePageTable = buffer; + void *pageDirectory = buffer; + memset(pageDirectory, 0, 0xFF8); buffer += 0x1000; kernelDataPageTable = buffer; buffer += 0x1000; - kernelUtilityPages = buffer; + kernelCodePageTable = buffer; buffer += 0x1000; - physicalPages = buffer; + temporaryPage = buffer; + buffer += 0x1000; + kernelPhysicalPages = buffer; buffer += sizeof(PagingInfo); kernelVirtualPages = buffer; buffer += sizeof(PagingInfo); - memset(physicalPages, 0, 2 * sizeof(PagingInfo)); + memset(kernelPhysicalPages, 0, 2 * sizeof(PagingInfo)); for (uint32_t i = 0; i < endPageId; i++) { - reservePage(physicalPages, i); + reservePage(kernelPhysicalPages, i); } for (uint32_t i = 0; i < 0x800; i++) { reservePage(kernelVirtualPages, i + 0xFF800); } - memset(kernelUtilityPages, 0, 0x1000); - mapDirectoryEntry(kernelDirectory, 0, kernelUtilityPages, - kernelVirtualPages); - physicalPages->pageSearchStart = endPageId; + kernelPhysicalPages->pageSearchStart = endPageId; + kernelVirtualPages->pageSearchStart = 0; + kernelVirtualPages->pageDirectory = pageDirectory; } void reservePage(PagingInfo *info, uint32_t pageId) { @@ -115,12 +124,12 @@ uint32_t physicalPageStart = U32(address) >> 12; uint32_t virtualPageStart = findMultiplePages(kernelVirtualPages, size); for (uint32_t i = 0; i < size; i++) { - reservePage(physicalPages, physicalPageStart + i); + reservePage(kernelPhysicalPages, physicalPageStart + i); reservePage(kernelVirtualPages, virtualPageStart + i); - kernelUtilityPages[virtualPageStart + i].targetAddress = - physicalPageStart + i; - kernelUtilityPages[virtualPageStart + i].writable = 1; - kernelUtilityPages[virtualPageStart + i].present = 1; + } + for (uint32_t i = 0; i < size; i++) { + mapPage(kernelVirtualPages, PTR((physicalPageStart + i) << 12), + PTR((virtualPageStart + i) << 12)); } return PTR((virtualPageStart << 12) + (U32(address) & 0xFFF)); } @@ -128,3 +137,42 @@ void *kernelMapPhysical(void *address) { return kernelMapMultiplePhysicalPages(address, 1); } + +void mapPage(PagingInfo *info, void *physical, void *virtual) { + VirtualAddress *address = (void *)&virtual; + PageDirectoryEntry *directory = info->pageDirectory; + if (!directory[address->pageDirectoryIndex].present) { + uint32_t newPageTable = findPage(kernelPhysicalPages); + reservePage(kernelPhysicalPages, newPageTable); + void *temporary = mapTemporary(PTR(newPageTable << 12)); + memset(temporary, 0, 0x1000); + directory[address->pageDirectoryIndex].pageTableID = newPageTable; + directory[address->pageDirectoryIndex].present = 1; + directory[address->pageDirectoryIndex].writable = 1; + } + void *pageTablePhysical = + PTR(directory[address->pageDirectoryIndex].pageTableID << 12); + void *temporary = mapTemporary(pageTablePhysical); + PageTableEntry *pageTable = temporary; + pageTable[address->pageTableIndex].targetAddress = U32(physical) >> 12; + pageTable[address->pageTableIndex].present = 1; + pageTable[address->pageTableIndex].writable = 1; + invalidatePage(U32(virtual) >> 12); +} + +void *getPage() { + uint32_t physical = findPage(kernelPhysicalPages); + reservePage(kernelPhysicalPages, physical); + uint32_t virtual = findPage(kernelVirtualPages); + reservePage(kernelVirtualPages, virtual); + mapPage(kernelVirtualPages, PTR(physical << 12), PTR(virtual << 12)); + return PTR(virtual << 12); +} + +void sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress) { + PagingInfo *source = kernelVirtualPages; + void *physicalSource = + getPhysicalAddress(sourceAddress, source->pageDirectory); + mapPage(destination, physicalSource, destinationAddress); +} diff --git a/src/kernel/memory/paging.h b/src/kernel/memory/paging.h index 208f670..c6c3e10 100644 --- a/src/kernel/memory/paging.h +++ b/src/kernel/memory/paging.h @@ -7,18 +7,6 @@ uint32_t present : 1; uint32_t writable : 1; uint32_t belongsToUserProcess : 1; - uint32_t reserved : 2; - uint32_t accessed : 1; - uint32_t dirty : 1; - uint32_t reserved2 : 2; - uint32_t available : 3; - uint32_t pageTableID : 20; -} __attribute__((packed)) PageDirectoryEntry; - -typedef struct { - uint32_t present : 1; - uint32_t writable : 1; - uint32_t belongsToUserProcess : 1; uint32_t writeThrough : 1; uint32_t isVolatile : 1; // disables the cpu cache uint32_t accessed : 1; @@ -30,13 +18,6 @@ } __attribute__((packed)) PageTableEntry; typedef struct { - uint32_t isPageAllocated[0x8000]; - uint32_t isPageAllocatedCoarse[0x400]; - uint32_t isPageTableInUse[0x20]; - uint32_t pageSearchStart; -} PagingInfo; - -typedef struct { uint32_t pageOffset : 12; uint32_t pageTableIndex : 10; uint32_t pageDirectoryIndex : 10; diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index cb41d70..5731bda 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -3,11 +3,39 @@ #include +typedef struct { + uint32_t present : 1; + uint32_t writable : 1; + uint32_t belongsToUserProcess : 1; + uint32_t reserved : 2; + uint32_t accessed : 1; + uint32_t dirty : 1; + uint32_t reserved2 : 2; + uint32_t available : 3; + uint32_t pageTableID : 20; +} __attribute__((packed)) PageDirectoryEntry; + +typedef struct { + PageDirectoryEntry *pageDirectory; + uint32_t isPageTableInUse[0x20]; + uint32_t isPageAllocated[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 *getPage(); +extern void sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress); + +extern void *getPhysicalAddressKernel(void *address); #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h new file mode 100644 index 0000000..b746d66 --- /dev/null +++ b/src/kernel/include/service.h @@ -0,0 +1,6 @@ +#ifndef SERVICE_H +#define SERVICE_H + +extern void loadElf(void *fileData); + +#endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index ac89942..748a044 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -2,14 +2,18 @@ #define UTIL_H #include +#include #define U32(x) (uint32_t)(uintptr_t)(x) #define PTR(x) (void *)(uintptr_t)(x) #define NULL PTR(0) +#define MIN(x, y) (x < y ? x : y) + #define PAGE_COUNT(x) (((x - 1) / 4096) + 1) extern bool stringEquals(char *string1, char *string2); +extern void memcpy(void *source, void *destination, uint32_t size); #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 7fdcc82..9b91775 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -1,13 +1,15 @@ #include #include +#include #include void kernelMain(void *multibootInfo) { setupMemory(); - void *address = kernelMapPhysical(multibootInfo); + void *address = kernelMapMultiplePhysicalPages(multibootInfo, 4); uint32_t tarSize = 0; void *initrd = findInitrd(address, &tarSize); void *loaderProgram = findTarFile(initrd, tarSize, "initrd/loader"); + loadElf(loaderProgram); asm("mov %%eax, %0" ::"r"(loaderProgram)); while (1) ; diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c new file mode 100644 index 0000000..b6b9b40 --- /dev/null +++ b/src/kernel/memory/malloc.c @@ -0,0 +1,76 @@ +#include "malloc.h" +#include + +#define LOG2(X) ((unsigned)(64 - __builtin_clzll((X)) - 1)) + +AllocationData allocationData; + +void *reserveBlock(AllocationBlock *block, uint8_t coarse, uint8_t fine) { + block->allocatedFine[coarse] |= 1 << fine; + block->allocatedCoarse |= 1 << coarse; + for (uint8_t i = 0; i < 32; i++) { + if (block->allocatedFine[coarse] & 1 << i) { + continue; + } + block->allocatedCoarse &= ~(1 << coarse); + break; + } + return ((uint8_t *)block) + block->blockSize * (32 * coarse + fine); +} + +void *malloc(uint32_t size) { + uint32_t sizeBit = LOG2(size) + 1; + if (sizeBit > 10) { + return getPage(); + } + AllocationBlock *block = allocationData[sizeBit], *last = 0; + while (1) { + if (!block) { + block = getPage(); + memset(block, 0, 4096); + block->blockSize = 1 << sizeBit; + if (last) { + block->previous = last; + last->next = block; + } else { + allocationData[sizeBit] = block; + block->previous = (void *)(uintptr_t)sizeBit; + } + block->magic = ALLOCATION_MAGIC; + } + if (block->allocatedCoarse == ~0) { + goto end; + } + for (uint8_t coarse = 0; coarse < 32; coarse++) { + for (uint8_t fine = 0; fine < 32; fine++) { + if (block->allocatedFine[coarse] & (1 << fine)) { + continue; + } + return reserveBlock(block, coarse, fine); + } + } + end: + last = block; + block = block->next; + } +} + +void free(void *location) { + AllocationBlock *block = (void *)((uintptr_t)location & ~0xFFF); + if (block->magic != ALLOCATION_MAGIC) { + // freePage(location); + return; + } + uint16_t index = (uint16_t)((uintptr_t)location & 0xFFF) / block->blockSize; + uint8_t coarse = index / 32; + uint8_t fine = index % 32; + block->allocatedFine[coarse] &= ~(1 << fine); + block->allocatedCoarse &= ~(1 << coarse); + for (uint8_t i = 0; i < 32; i++) { + if (block->allocatedFine[coarse] & (1 << i)) { + continue; + } + block->allocatedCoarse |= 1 << coarse; + return; + } +} diff --git a/src/kernel/memory/malloc.h b/src/kernel/memory/malloc.h new file mode 100644 index 0000000..16e0c80 --- /dev/null +++ b/src/kernel/memory/malloc.h @@ -0,0 +1,20 @@ +#ifndef ALLOC_H +#define ALLOC_H + +#include + +#define ALLOCATION_MAGIC 0x44BB33DD + +typedef struct AllocationBlock { + uint8_t data[3948]; + uint32_t allocatedFine[32]; + uint32_t allocatedCoarse; + uint32_t blockSize; + struct AllocationBlock *next; + struct AllocationBlock *previous; + uint32_t magic; +} AllocationBlock; + +typedef AllocationBlock *AllocationData[12]; + +#endif diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index 0213f25..3bd35e9 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -2,13 +2,18 @@ #include #include -PageDirectoryEntry *kernelDirectory; -PageTableEntry *kernelCodePageTable, *kernelDataPageTable, *kernelUtilityPages; +PageTableEntry *kernelCodePageTable, *kernelDataPageTable; -PagingInfo *physicalPages, *kernelVirtualPages; +PagingInfo *kernelPhysicalPages, *kernelVirtualPages; + +void *temporaryPage; void reservePage(PagingInfo *info, uint32_t pageId); +void invalidatePage(uint32_t pageId) { + asm("invlpg (%0)" ::"r"(pageId << 12) : "memory"); +} + void *kernelGetVirtualAddress(void *_address) { uint32_t address = (uint32_t)(uintptr_t)_address; if (address < 0x100000) { @@ -23,52 +28,56 @@ return 0; } +void *mapTemporary(void *physical) { + kernelDataPageTable[3].targetAddress = U32(physical) >> 12; + kernelDataPageTable[3].writable = 1; + kernelDataPageTable[3].present = 1; + invalidatePage(0xFF803); + return temporaryPage; +} + void *getPhysicalAddress(void *address, PageDirectoryEntry *pageDirectory) { VirtualAddress *virtual = (void *)&address; uint32_t pageTableLocation = pageDirectory[virtual->pageDirectoryIndex].pageTableID; PageTableEntry *pageTable = PTR(pageTableLocation << 12); - pageTable = kernelGetVirtualAddress(pageTable); + pageTable = mapTemporary(pageTable); uint32_t pageBase = pageTable[virtual->pageTableIndex].targetAddress; return PTR(pageBase << 12 | virtual->pageOffset); } -void mapDirectoryEntry(PageDirectoryEntry *directory, uint32_t pageTableIndex, - PageTableEntry *pageTable, PagingInfo *pagingInfo) { - directory[pageTableIndex].pageTableID = - U32(getPhysicalAddress(pageTable, directory)) >> 12; - directory[pageTableIndex].writable = 1; - directory[pageTableIndex].present = 1; - pagingInfo->isPageTableInUse[pageTableIndex / 32] |= - 1 << (pageTableIndex % 32); +void *getPhysicalAddressKernel(void *address) { + return getPhysicalAddress(address, kernelVirtualPages->pageDirectory); } +uint32_t findPage(PagingInfo *info); +void mapPage(PagingInfo *info, void *physical, void *virtual); + void reservePagesUntilPhysical(uint32_t endPageId) { void *buffer = (void *)0xFF800000; - kernelDirectory = buffer; - memset(kernelDirectory, 0, 0xFF8); - buffer += 0x1000; - kernelCodePageTable = buffer; + void *pageDirectory = buffer; + memset(pageDirectory, 0, 0xFF8); buffer += 0x1000; kernelDataPageTable = buffer; buffer += 0x1000; - kernelUtilityPages = buffer; + kernelCodePageTable = buffer; buffer += 0x1000; - physicalPages = buffer; + temporaryPage = buffer; + buffer += 0x1000; + kernelPhysicalPages = buffer; buffer += sizeof(PagingInfo); kernelVirtualPages = buffer; buffer += sizeof(PagingInfo); - memset(physicalPages, 0, 2 * sizeof(PagingInfo)); + memset(kernelPhysicalPages, 0, 2 * sizeof(PagingInfo)); for (uint32_t i = 0; i < endPageId; i++) { - reservePage(physicalPages, i); + reservePage(kernelPhysicalPages, i); } for (uint32_t i = 0; i < 0x800; i++) { reservePage(kernelVirtualPages, i + 0xFF800); } - memset(kernelUtilityPages, 0, 0x1000); - mapDirectoryEntry(kernelDirectory, 0, kernelUtilityPages, - kernelVirtualPages); - physicalPages->pageSearchStart = endPageId; + kernelPhysicalPages->pageSearchStart = endPageId; + kernelVirtualPages->pageSearchStart = 0; + kernelVirtualPages->pageDirectory = pageDirectory; } void reservePage(PagingInfo *info, uint32_t pageId) { @@ -115,12 +124,12 @@ uint32_t physicalPageStart = U32(address) >> 12; uint32_t virtualPageStart = findMultiplePages(kernelVirtualPages, size); for (uint32_t i = 0; i < size; i++) { - reservePage(physicalPages, physicalPageStart + i); + reservePage(kernelPhysicalPages, physicalPageStart + i); reservePage(kernelVirtualPages, virtualPageStart + i); - kernelUtilityPages[virtualPageStart + i].targetAddress = - physicalPageStart + i; - kernelUtilityPages[virtualPageStart + i].writable = 1; - kernelUtilityPages[virtualPageStart + i].present = 1; + } + for (uint32_t i = 0; i < size; i++) { + mapPage(kernelVirtualPages, PTR((physicalPageStart + i) << 12), + PTR((virtualPageStart + i) << 12)); } return PTR((virtualPageStart << 12) + (U32(address) & 0xFFF)); } @@ -128,3 +137,42 @@ void *kernelMapPhysical(void *address) { return kernelMapMultiplePhysicalPages(address, 1); } + +void mapPage(PagingInfo *info, void *physical, void *virtual) { + VirtualAddress *address = (void *)&virtual; + PageDirectoryEntry *directory = info->pageDirectory; + if (!directory[address->pageDirectoryIndex].present) { + uint32_t newPageTable = findPage(kernelPhysicalPages); + reservePage(kernelPhysicalPages, newPageTable); + void *temporary = mapTemporary(PTR(newPageTable << 12)); + memset(temporary, 0, 0x1000); + directory[address->pageDirectoryIndex].pageTableID = newPageTable; + directory[address->pageDirectoryIndex].present = 1; + directory[address->pageDirectoryIndex].writable = 1; + } + void *pageTablePhysical = + PTR(directory[address->pageDirectoryIndex].pageTableID << 12); + void *temporary = mapTemporary(pageTablePhysical); + PageTableEntry *pageTable = temporary; + pageTable[address->pageTableIndex].targetAddress = U32(physical) >> 12; + pageTable[address->pageTableIndex].present = 1; + pageTable[address->pageTableIndex].writable = 1; + invalidatePage(U32(virtual) >> 12); +} + +void *getPage() { + uint32_t physical = findPage(kernelPhysicalPages); + reservePage(kernelPhysicalPages, physical); + uint32_t virtual = findPage(kernelVirtualPages); + reservePage(kernelVirtualPages, virtual); + mapPage(kernelVirtualPages, PTR(physical << 12), PTR(virtual << 12)); + return PTR(virtual << 12); +} + +void sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress) { + PagingInfo *source = kernelVirtualPages; + void *physicalSource = + getPhysicalAddress(sourceAddress, source->pageDirectory); + mapPage(destination, physicalSource, destinationAddress); +} diff --git a/src/kernel/memory/paging.h b/src/kernel/memory/paging.h index 208f670..c6c3e10 100644 --- a/src/kernel/memory/paging.h +++ b/src/kernel/memory/paging.h @@ -7,18 +7,6 @@ uint32_t present : 1; uint32_t writable : 1; uint32_t belongsToUserProcess : 1; - uint32_t reserved : 2; - uint32_t accessed : 1; - uint32_t dirty : 1; - uint32_t reserved2 : 2; - uint32_t available : 3; - uint32_t pageTableID : 20; -} __attribute__((packed)) PageDirectoryEntry; - -typedef struct { - uint32_t present : 1; - uint32_t writable : 1; - uint32_t belongsToUserProcess : 1; uint32_t writeThrough : 1; uint32_t isVolatile : 1; // disables the cpu cache uint32_t accessed : 1; @@ -30,13 +18,6 @@ } __attribute__((packed)) PageTableEntry; typedef struct { - uint32_t isPageAllocated[0x8000]; - uint32_t isPageAllocatedCoarse[0x400]; - uint32_t isPageTableInUse[0x20]; - uint32_t pageSearchStart; -} PagingInfo; - -typedef struct { uint32_t pageOffset : 12; uint32_t pageTableIndex : 10; uint32_t pageDirectoryIndex : 10; diff --git a/src/kernel/service/elf.h b/src/kernel/service/elf.h new file mode 100644 index 0000000..af9e01c --- /dev/null +++ b/src/kernel/service/elf.h @@ -0,0 +1,52 @@ +#ifndef ELF_H +#define ELF_H + +#include + +typedef struct { + uint32_t magic; + uint8_t is64BitFile; + uint8_t endianness; + uint8_t elfHeaderVersion; + uint8_t osABI; + uint32_t unused0, unused1; + uint16_t flags; + uint16_t instructionSet; + uint32_t elfVersion; + uint32_t entryPosition; + uint32_t programHeaderTablePosition; + uint32_t sectionHeaderTablePosition; + uint32_t architectureFlags; + uint16_t headerSize; + uint16_t programHeaderEntrySize; + uint16_t programHeaderEntryCount; + uint16_t sectionHeaderEntrySize; + uint16_t sectionHeaderEntryCount; + uint16_t sectionNamesHeaderTableIndex; +} ElfHeader; + +typedef struct { + uint16_t segmentType; + uint32_t dataOffset; + uint32_t virtualAddress; + uint32_t undefined; + uint32_t segmentFileSize; + uint32_t segmentMemorySize; + uint32_t flags; + uint32_t alignment; +} ProgramHeader; + +typedef struct { + uint32_t stringTableNameIndex; + uint32_t type; + uint32_t flags; + uint32_t virtualAddress; + uint32_t offset; + uint32_t size; + uint32_t link; + uint32_t info; + uint32_t alignment; + uint32_t entrySize; +} SectionHeader; + +#endif diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index cb41d70..5731bda 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -3,11 +3,39 @@ #include +typedef struct { + uint32_t present : 1; + uint32_t writable : 1; + uint32_t belongsToUserProcess : 1; + uint32_t reserved : 2; + uint32_t accessed : 1; + uint32_t dirty : 1; + uint32_t reserved2 : 2; + uint32_t available : 3; + uint32_t pageTableID : 20; +} __attribute__((packed)) PageDirectoryEntry; + +typedef struct { + PageDirectoryEntry *pageDirectory; + uint32_t isPageTableInUse[0x20]; + uint32_t isPageAllocated[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 *getPage(); +extern void sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress); + +extern void *getPhysicalAddressKernel(void *address); #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h new file mode 100644 index 0000000..b746d66 --- /dev/null +++ b/src/kernel/include/service.h @@ -0,0 +1,6 @@ +#ifndef SERVICE_H +#define SERVICE_H + +extern void loadElf(void *fileData); + +#endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index ac89942..748a044 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -2,14 +2,18 @@ #define UTIL_H #include +#include #define U32(x) (uint32_t)(uintptr_t)(x) #define PTR(x) (void *)(uintptr_t)(x) #define NULL PTR(0) +#define MIN(x, y) (x < y ? x : y) + #define PAGE_COUNT(x) (((x - 1) / 4096) + 1) extern bool stringEquals(char *string1, char *string2); +extern void memcpy(void *source, void *destination, uint32_t size); #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 7fdcc82..9b91775 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -1,13 +1,15 @@ #include #include +#include #include void kernelMain(void *multibootInfo) { setupMemory(); - void *address = kernelMapPhysical(multibootInfo); + void *address = kernelMapMultiplePhysicalPages(multibootInfo, 4); uint32_t tarSize = 0; void *initrd = findInitrd(address, &tarSize); void *loaderProgram = findTarFile(initrd, tarSize, "initrd/loader"); + loadElf(loaderProgram); asm("mov %%eax, %0" ::"r"(loaderProgram)); while (1) ; diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c new file mode 100644 index 0000000..b6b9b40 --- /dev/null +++ b/src/kernel/memory/malloc.c @@ -0,0 +1,76 @@ +#include "malloc.h" +#include + +#define LOG2(X) ((unsigned)(64 - __builtin_clzll((X)) - 1)) + +AllocationData allocationData; + +void *reserveBlock(AllocationBlock *block, uint8_t coarse, uint8_t fine) { + block->allocatedFine[coarse] |= 1 << fine; + block->allocatedCoarse |= 1 << coarse; + for (uint8_t i = 0; i < 32; i++) { + if (block->allocatedFine[coarse] & 1 << i) { + continue; + } + block->allocatedCoarse &= ~(1 << coarse); + break; + } + return ((uint8_t *)block) + block->blockSize * (32 * coarse + fine); +} + +void *malloc(uint32_t size) { + uint32_t sizeBit = LOG2(size) + 1; + if (sizeBit > 10) { + return getPage(); + } + AllocationBlock *block = allocationData[sizeBit], *last = 0; + while (1) { + if (!block) { + block = getPage(); + memset(block, 0, 4096); + block->blockSize = 1 << sizeBit; + if (last) { + block->previous = last; + last->next = block; + } else { + allocationData[sizeBit] = block; + block->previous = (void *)(uintptr_t)sizeBit; + } + block->magic = ALLOCATION_MAGIC; + } + if (block->allocatedCoarse == ~0) { + goto end; + } + for (uint8_t coarse = 0; coarse < 32; coarse++) { + for (uint8_t fine = 0; fine < 32; fine++) { + if (block->allocatedFine[coarse] & (1 << fine)) { + continue; + } + return reserveBlock(block, coarse, fine); + } + } + end: + last = block; + block = block->next; + } +} + +void free(void *location) { + AllocationBlock *block = (void *)((uintptr_t)location & ~0xFFF); + if (block->magic != ALLOCATION_MAGIC) { + // freePage(location); + return; + } + uint16_t index = (uint16_t)((uintptr_t)location & 0xFFF) / block->blockSize; + uint8_t coarse = index / 32; + uint8_t fine = index % 32; + block->allocatedFine[coarse] &= ~(1 << fine); + block->allocatedCoarse &= ~(1 << coarse); + for (uint8_t i = 0; i < 32; i++) { + if (block->allocatedFine[coarse] & (1 << i)) { + continue; + } + block->allocatedCoarse |= 1 << coarse; + return; + } +} diff --git a/src/kernel/memory/malloc.h b/src/kernel/memory/malloc.h new file mode 100644 index 0000000..16e0c80 --- /dev/null +++ b/src/kernel/memory/malloc.h @@ -0,0 +1,20 @@ +#ifndef ALLOC_H +#define ALLOC_H + +#include + +#define ALLOCATION_MAGIC 0x44BB33DD + +typedef struct AllocationBlock { + uint8_t data[3948]; + uint32_t allocatedFine[32]; + uint32_t allocatedCoarse; + uint32_t blockSize; + struct AllocationBlock *next; + struct AllocationBlock *previous; + uint32_t magic; +} AllocationBlock; + +typedef AllocationBlock *AllocationData[12]; + +#endif diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index 0213f25..3bd35e9 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -2,13 +2,18 @@ #include #include -PageDirectoryEntry *kernelDirectory; -PageTableEntry *kernelCodePageTable, *kernelDataPageTable, *kernelUtilityPages; +PageTableEntry *kernelCodePageTable, *kernelDataPageTable; -PagingInfo *physicalPages, *kernelVirtualPages; +PagingInfo *kernelPhysicalPages, *kernelVirtualPages; + +void *temporaryPage; void reservePage(PagingInfo *info, uint32_t pageId); +void invalidatePage(uint32_t pageId) { + asm("invlpg (%0)" ::"r"(pageId << 12) : "memory"); +} + void *kernelGetVirtualAddress(void *_address) { uint32_t address = (uint32_t)(uintptr_t)_address; if (address < 0x100000) { @@ -23,52 +28,56 @@ return 0; } +void *mapTemporary(void *physical) { + kernelDataPageTable[3].targetAddress = U32(physical) >> 12; + kernelDataPageTable[3].writable = 1; + kernelDataPageTable[3].present = 1; + invalidatePage(0xFF803); + return temporaryPage; +} + void *getPhysicalAddress(void *address, PageDirectoryEntry *pageDirectory) { VirtualAddress *virtual = (void *)&address; uint32_t pageTableLocation = pageDirectory[virtual->pageDirectoryIndex].pageTableID; PageTableEntry *pageTable = PTR(pageTableLocation << 12); - pageTable = kernelGetVirtualAddress(pageTable); + pageTable = mapTemporary(pageTable); uint32_t pageBase = pageTable[virtual->pageTableIndex].targetAddress; return PTR(pageBase << 12 | virtual->pageOffset); } -void mapDirectoryEntry(PageDirectoryEntry *directory, uint32_t pageTableIndex, - PageTableEntry *pageTable, PagingInfo *pagingInfo) { - directory[pageTableIndex].pageTableID = - U32(getPhysicalAddress(pageTable, directory)) >> 12; - directory[pageTableIndex].writable = 1; - directory[pageTableIndex].present = 1; - pagingInfo->isPageTableInUse[pageTableIndex / 32] |= - 1 << (pageTableIndex % 32); +void *getPhysicalAddressKernel(void *address) { + return getPhysicalAddress(address, kernelVirtualPages->pageDirectory); } +uint32_t findPage(PagingInfo *info); +void mapPage(PagingInfo *info, void *physical, void *virtual); + void reservePagesUntilPhysical(uint32_t endPageId) { void *buffer = (void *)0xFF800000; - kernelDirectory = buffer; - memset(kernelDirectory, 0, 0xFF8); - buffer += 0x1000; - kernelCodePageTable = buffer; + void *pageDirectory = buffer; + memset(pageDirectory, 0, 0xFF8); buffer += 0x1000; kernelDataPageTable = buffer; buffer += 0x1000; - kernelUtilityPages = buffer; + kernelCodePageTable = buffer; buffer += 0x1000; - physicalPages = buffer; + temporaryPage = buffer; + buffer += 0x1000; + kernelPhysicalPages = buffer; buffer += sizeof(PagingInfo); kernelVirtualPages = buffer; buffer += sizeof(PagingInfo); - memset(physicalPages, 0, 2 * sizeof(PagingInfo)); + memset(kernelPhysicalPages, 0, 2 * sizeof(PagingInfo)); for (uint32_t i = 0; i < endPageId; i++) { - reservePage(physicalPages, i); + reservePage(kernelPhysicalPages, i); } for (uint32_t i = 0; i < 0x800; i++) { reservePage(kernelVirtualPages, i + 0xFF800); } - memset(kernelUtilityPages, 0, 0x1000); - mapDirectoryEntry(kernelDirectory, 0, kernelUtilityPages, - kernelVirtualPages); - physicalPages->pageSearchStart = endPageId; + kernelPhysicalPages->pageSearchStart = endPageId; + kernelVirtualPages->pageSearchStart = 0; + kernelVirtualPages->pageDirectory = pageDirectory; } void reservePage(PagingInfo *info, uint32_t pageId) { @@ -115,12 +124,12 @@ uint32_t physicalPageStart = U32(address) >> 12; uint32_t virtualPageStart = findMultiplePages(kernelVirtualPages, size); for (uint32_t i = 0; i < size; i++) { - reservePage(physicalPages, physicalPageStart + i); + reservePage(kernelPhysicalPages, physicalPageStart + i); reservePage(kernelVirtualPages, virtualPageStart + i); - kernelUtilityPages[virtualPageStart + i].targetAddress = - physicalPageStart + i; - kernelUtilityPages[virtualPageStart + i].writable = 1; - kernelUtilityPages[virtualPageStart + i].present = 1; + } + for (uint32_t i = 0; i < size; i++) { + mapPage(kernelVirtualPages, PTR((physicalPageStart + i) << 12), + PTR((virtualPageStart + i) << 12)); } return PTR((virtualPageStart << 12) + (U32(address) & 0xFFF)); } @@ -128,3 +137,42 @@ void *kernelMapPhysical(void *address) { return kernelMapMultiplePhysicalPages(address, 1); } + +void mapPage(PagingInfo *info, void *physical, void *virtual) { + VirtualAddress *address = (void *)&virtual; + PageDirectoryEntry *directory = info->pageDirectory; + if (!directory[address->pageDirectoryIndex].present) { + uint32_t newPageTable = findPage(kernelPhysicalPages); + reservePage(kernelPhysicalPages, newPageTable); + void *temporary = mapTemporary(PTR(newPageTable << 12)); + memset(temporary, 0, 0x1000); + directory[address->pageDirectoryIndex].pageTableID = newPageTable; + directory[address->pageDirectoryIndex].present = 1; + directory[address->pageDirectoryIndex].writable = 1; + } + void *pageTablePhysical = + PTR(directory[address->pageDirectoryIndex].pageTableID << 12); + void *temporary = mapTemporary(pageTablePhysical); + PageTableEntry *pageTable = temporary; + pageTable[address->pageTableIndex].targetAddress = U32(physical) >> 12; + pageTable[address->pageTableIndex].present = 1; + pageTable[address->pageTableIndex].writable = 1; + invalidatePage(U32(virtual) >> 12); +} + +void *getPage() { + uint32_t physical = findPage(kernelPhysicalPages); + reservePage(kernelPhysicalPages, physical); + uint32_t virtual = findPage(kernelVirtualPages); + reservePage(kernelVirtualPages, virtual); + mapPage(kernelVirtualPages, PTR(physical << 12), PTR(virtual << 12)); + return PTR(virtual << 12); +} + +void sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress) { + PagingInfo *source = kernelVirtualPages; + void *physicalSource = + getPhysicalAddress(sourceAddress, source->pageDirectory); + mapPage(destination, physicalSource, destinationAddress); +} diff --git a/src/kernel/memory/paging.h b/src/kernel/memory/paging.h index 208f670..c6c3e10 100644 --- a/src/kernel/memory/paging.h +++ b/src/kernel/memory/paging.h @@ -7,18 +7,6 @@ uint32_t present : 1; uint32_t writable : 1; uint32_t belongsToUserProcess : 1; - uint32_t reserved : 2; - uint32_t accessed : 1; - uint32_t dirty : 1; - uint32_t reserved2 : 2; - uint32_t available : 3; - uint32_t pageTableID : 20; -} __attribute__((packed)) PageDirectoryEntry; - -typedef struct { - uint32_t present : 1; - uint32_t writable : 1; - uint32_t belongsToUserProcess : 1; uint32_t writeThrough : 1; uint32_t isVolatile : 1; // disables the cpu cache uint32_t accessed : 1; @@ -30,13 +18,6 @@ } __attribute__((packed)) PageTableEntry; typedef struct { - uint32_t isPageAllocated[0x8000]; - uint32_t isPageAllocatedCoarse[0x400]; - uint32_t isPageTableInUse[0x20]; - uint32_t pageSearchStart; -} PagingInfo; - -typedef struct { uint32_t pageOffset : 12; uint32_t pageTableIndex : 10; uint32_t pageDirectoryIndex : 10; diff --git a/src/kernel/service/elf.h b/src/kernel/service/elf.h new file mode 100644 index 0000000..af9e01c --- /dev/null +++ b/src/kernel/service/elf.h @@ -0,0 +1,52 @@ +#ifndef ELF_H +#define ELF_H + +#include + +typedef struct { + uint32_t magic; + uint8_t is64BitFile; + uint8_t endianness; + uint8_t elfHeaderVersion; + uint8_t osABI; + uint32_t unused0, unused1; + uint16_t flags; + uint16_t instructionSet; + uint32_t elfVersion; + uint32_t entryPosition; + uint32_t programHeaderTablePosition; + uint32_t sectionHeaderTablePosition; + uint32_t architectureFlags; + uint16_t headerSize; + uint16_t programHeaderEntrySize; + uint16_t programHeaderEntryCount; + uint16_t sectionHeaderEntrySize; + uint16_t sectionHeaderEntryCount; + uint16_t sectionNamesHeaderTableIndex; +} ElfHeader; + +typedef struct { + uint16_t segmentType; + uint32_t dataOffset; + uint32_t virtualAddress; + uint32_t undefined; + uint32_t segmentFileSize; + uint32_t segmentMemorySize; + uint32_t flags; + uint32_t alignment; +} ProgramHeader; + +typedef struct { + uint32_t stringTableNameIndex; + uint32_t type; + uint32_t flags; + uint32_t virtualAddress; + uint32_t offset; + uint32_t size; + uint32_t link; + uint32_t info; + uint32_t alignment; + uint32_t entrySize; +} SectionHeader; + +#endif diff --git a/src/kernel/service/service.h b/src/kernel/service/service.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/kernel/service/service.h diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index cb41d70..5731bda 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -3,11 +3,39 @@ #include +typedef struct { + uint32_t present : 1; + uint32_t writable : 1; + uint32_t belongsToUserProcess : 1; + uint32_t reserved : 2; + uint32_t accessed : 1; + uint32_t dirty : 1; + uint32_t reserved2 : 2; + uint32_t available : 3; + uint32_t pageTableID : 20; +} __attribute__((packed)) PageDirectoryEntry; + +typedef struct { + PageDirectoryEntry *pageDirectory; + uint32_t isPageTableInUse[0x20]; + uint32_t isPageAllocated[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 *getPage(); +extern void sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress); + +extern void *getPhysicalAddressKernel(void *address); #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h new file mode 100644 index 0000000..b746d66 --- /dev/null +++ b/src/kernel/include/service.h @@ -0,0 +1,6 @@ +#ifndef SERVICE_H +#define SERVICE_H + +extern void loadElf(void *fileData); + +#endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index ac89942..748a044 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -2,14 +2,18 @@ #define UTIL_H #include +#include #define U32(x) (uint32_t)(uintptr_t)(x) #define PTR(x) (void *)(uintptr_t)(x) #define NULL PTR(0) +#define MIN(x, y) (x < y ? x : y) + #define PAGE_COUNT(x) (((x - 1) / 4096) + 1) extern bool stringEquals(char *string1, char *string2); +extern void memcpy(void *source, void *destination, uint32_t size); #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 7fdcc82..9b91775 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -1,13 +1,15 @@ #include #include +#include #include void kernelMain(void *multibootInfo) { setupMemory(); - void *address = kernelMapPhysical(multibootInfo); + void *address = kernelMapMultiplePhysicalPages(multibootInfo, 4); uint32_t tarSize = 0; void *initrd = findInitrd(address, &tarSize); void *loaderProgram = findTarFile(initrd, tarSize, "initrd/loader"); + loadElf(loaderProgram); asm("mov %%eax, %0" ::"r"(loaderProgram)); while (1) ; diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c new file mode 100644 index 0000000..b6b9b40 --- /dev/null +++ b/src/kernel/memory/malloc.c @@ -0,0 +1,76 @@ +#include "malloc.h" +#include + +#define LOG2(X) ((unsigned)(64 - __builtin_clzll((X)) - 1)) + +AllocationData allocationData; + +void *reserveBlock(AllocationBlock *block, uint8_t coarse, uint8_t fine) { + block->allocatedFine[coarse] |= 1 << fine; + block->allocatedCoarse |= 1 << coarse; + for (uint8_t i = 0; i < 32; i++) { + if (block->allocatedFine[coarse] & 1 << i) { + continue; + } + block->allocatedCoarse &= ~(1 << coarse); + break; + } + return ((uint8_t *)block) + block->blockSize * (32 * coarse + fine); +} + +void *malloc(uint32_t size) { + uint32_t sizeBit = LOG2(size) + 1; + if (sizeBit > 10) { + return getPage(); + } + AllocationBlock *block = allocationData[sizeBit], *last = 0; + while (1) { + if (!block) { + block = getPage(); + memset(block, 0, 4096); + block->blockSize = 1 << sizeBit; + if (last) { + block->previous = last; + last->next = block; + } else { + allocationData[sizeBit] = block; + block->previous = (void *)(uintptr_t)sizeBit; + } + block->magic = ALLOCATION_MAGIC; + } + if (block->allocatedCoarse == ~0) { + goto end; + } + for (uint8_t coarse = 0; coarse < 32; coarse++) { + for (uint8_t fine = 0; fine < 32; fine++) { + if (block->allocatedFine[coarse] & (1 << fine)) { + continue; + } + return reserveBlock(block, coarse, fine); + } + } + end: + last = block; + block = block->next; + } +} + +void free(void *location) { + AllocationBlock *block = (void *)((uintptr_t)location & ~0xFFF); + if (block->magic != ALLOCATION_MAGIC) { + // freePage(location); + return; + } + uint16_t index = (uint16_t)((uintptr_t)location & 0xFFF) / block->blockSize; + uint8_t coarse = index / 32; + uint8_t fine = index % 32; + block->allocatedFine[coarse] &= ~(1 << fine); + block->allocatedCoarse &= ~(1 << coarse); + for (uint8_t i = 0; i < 32; i++) { + if (block->allocatedFine[coarse] & (1 << i)) { + continue; + } + block->allocatedCoarse |= 1 << coarse; + return; + } +} diff --git a/src/kernel/memory/malloc.h b/src/kernel/memory/malloc.h new file mode 100644 index 0000000..16e0c80 --- /dev/null +++ b/src/kernel/memory/malloc.h @@ -0,0 +1,20 @@ +#ifndef ALLOC_H +#define ALLOC_H + +#include + +#define ALLOCATION_MAGIC 0x44BB33DD + +typedef struct AllocationBlock { + uint8_t data[3948]; + uint32_t allocatedFine[32]; + uint32_t allocatedCoarse; + uint32_t blockSize; + struct AllocationBlock *next; + struct AllocationBlock *previous; + uint32_t magic; +} AllocationBlock; + +typedef AllocationBlock *AllocationData[12]; + +#endif diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index 0213f25..3bd35e9 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -2,13 +2,18 @@ #include #include -PageDirectoryEntry *kernelDirectory; -PageTableEntry *kernelCodePageTable, *kernelDataPageTable, *kernelUtilityPages; +PageTableEntry *kernelCodePageTable, *kernelDataPageTable; -PagingInfo *physicalPages, *kernelVirtualPages; +PagingInfo *kernelPhysicalPages, *kernelVirtualPages; + +void *temporaryPage; void reservePage(PagingInfo *info, uint32_t pageId); +void invalidatePage(uint32_t pageId) { + asm("invlpg (%0)" ::"r"(pageId << 12) : "memory"); +} + void *kernelGetVirtualAddress(void *_address) { uint32_t address = (uint32_t)(uintptr_t)_address; if (address < 0x100000) { @@ -23,52 +28,56 @@ return 0; } +void *mapTemporary(void *physical) { + kernelDataPageTable[3].targetAddress = U32(physical) >> 12; + kernelDataPageTable[3].writable = 1; + kernelDataPageTable[3].present = 1; + invalidatePage(0xFF803); + return temporaryPage; +} + void *getPhysicalAddress(void *address, PageDirectoryEntry *pageDirectory) { VirtualAddress *virtual = (void *)&address; uint32_t pageTableLocation = pageDirectory[virtual->pageDirectoryIndex].pageTableID; PageTableEntry *pageTable = PTR(pageTableLocation << 12); - pageTable = kernelGetVirtualAddress(pageTable); + pageTable = mapTemporary(pageTable); uint32_t pageBase = pageTable[virtual->pageTableIndex].targetAddress; return PTR(pageBase << 12 | virtual->pageOffset); } -void mapDirectoryEntry(PageDirectoryEntry *directory, uint32_t pageTableIndex, - PageTableEntry *pageTable, PagingInfo *pagingInfo) { - directory[pageTableIndex].pageTableID = - U32(getPhysicalAddress(pageTable, directory)) >> 12; - directory[pageTableIndex].writable = 1; - directory[pageTableIndex].present = 1; - pagingInfo->isPageTableInUse[pageTableIndex / 32] |= - 1 << (pageTableIndex % 32); +void *getPhysicalAddressKernel(void *address) { + return getPhysicalAddress(address, kernelVirtualPages->pageDirectory); } +uint32_t findPage(PagingInfo *info); +void mapPage(PagingInfo *info, void *physical, void *virtual); + void reservePagesUntilPhysical(uint32_t endPageId) { void *buffer = (void *)0xFF800000; - kernelDirectory = buffer; - memset(kernelDirectory, 0, 0xFF8); - buffer += 0x1000; - kernelCodePageTable = buffer; + void *pageDirectory = buffer; + memset(pageDirectory, 0, 0xFF8); buffer += 0x1000; kernelDataPageTable = buffer; buffer += 0x1000; - kernelUtilityPages = buffer; + kernelCodePageTable = buffer; buffer += 0x1000; - physicalPages = buffer; + temporaryPage = buffer; + buffer += 0x1000; + kernelPhysicalPages = buffer; buffer += sizeof(PagingInfo); kernelVirtualPages = buffer; buffer += sizeof(PagingInfo); - memset(physicalPages, 0, 2 * sizeof(PagingInfo)); + memset(kernelPhysicalPages, 0, 2 * sizeof(PagingInfo)); for (uint32_t i = 0; i < endPageId; i++) { - reservePage(physicalPages, i); + reservePage(kernelPhysicalPages, i); } for (uint32_t i = 0; i < 0x800; i++) { reservePage(kernelVirtualPages, i + 0xFF800); } - memset(kernelUtilityPages, 0, 0x1000); - mapDirectoryEntry(kernelDirectory, 0, kernelUtilityPages, - kernelVirtualPages); - physicalPages->pageSearchStart = endPageId; + kernelPhysicalPages->pageSearchStart = endPageId; + kernelVirtualPages->pageSearchStart = 0; + kernelVirtualPages->pageDirectory = pageDirectory; } void reservePage(PagingInfo *info, uint32_t pageId) { @@ -115,12 +124,12 @@ uint32_t physicalPageStart = U32(address) >> 12; uint32_t virtualPageStart = findMultiplePages(kernelVirtualPages, size); for (uint32_t i = 0; i < size; i++) { - reservePage(physicalPages, physicalPageStart + i); + reservePage(kernelPhysicalPages, physicalPageStart + i); reservePage(kernelVirtualPages, virtualPageStart + i); - kernelUtilityPages[virtualPageStart + i].targetAddress = - physicalPageStart + i; - kernelUtilityPages[virtualPageStart + i].writable = 1; - kernelUtilityPages[virtualPageStart + i].present = 1; + } + for (uint32_t i = 0; i < size; i++) { + mapPage(kernelVirtualPages, PTR((physicalPageStart + i) << 12), + PTR((virtualPageStart + i) << 12)); } return PTR((virtualPageStart << 12) + (U32(address) & 0xFFF)); } @@ -128,3 +137,42 @@ void *kernelMapPhysical(void *address) { return kernelMapMultiplePhysicalPages(address, 1); } + +void mapPage(PagingInfo *info, void *physical, void *virtual) { + VirtualAddress *address = (void *)&virtual; + PageDirectoryEntry *directory = info->pageDirectory; + if (!directory[address->pageDirectoryIndex].present) { + uint32_t newPageTable = findPage(kernelPhysicalPages); + reservePage(kernelPhysicalPages, newPageTable); + void *temporary = mapTemporary(PTR(newPageTable << 12)); + memset(temporary, 0, 0x1000); + directory[address->pageDirectoryIndex].pageTableID = newPageTable; + directory[address->pageDirectoryIndex].present = 1; + directory[address->pageDirectoryIndex].writable = 1; + } + void *pageTablePhysical = + PTR(directory[address->pageDirectoryIndex].pageTableID << 12); + void *temporary = mapTemporary(pageTablePhysical); + PageTableEntry *pageTable = temporary; + pageTable[address->pageTableIndex].targetAddress = U32(physical) >> 12; + pageTable[address->pageTableIndex].present = 1; + pageTable[address->pageTableIndex].writable = 1; + invalidatePage(U32(virtual) >> 12); +} + +void *getPage() { + uint32_t physical = findPage(kernelPhysicalPages); + reservePage(kernelPhysicalPages, physical); + uint32_t virtual = findPage(kernelVirtualPages); + reservePage(kernelVirtualPages, virtual); + mapPage(kernelVirtualPages, PTR(physical << 12), PTR(virtual << 12)); + return PTR(virtual << 12); +} + +void sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress) { + PagingInfo *source = kernelVirtualPages; + void *physicalSource = + getPhysicalAddress(sourceAddress, source->pageDirectory); + mapPage(destination, physicalSource, destinationAddress); +} diff --git a/src/kernel/memory/paging.h b/src/kernel/memory/paging.h index 208f670..c6c3e10 100644 --- a/src/kernel/memory/paging.h +++ b/src/kernel/memory/paging.h @@ -7,18 +7,6 @@ uint32_t present : 1; uint32_t writable : 1; uint32_t belongsToUserProcess : 1; - uint32_t reserved : 2; - uint32_t accessed : 1; - uint32_t dirty : 1; - uint32_t reserved2 : 2; - uint32_t available : 3; - uint32_t pageTableID : 20; -} __attribute__((packed)) PageDirectoryEntry; - -typedef struct { - uint32_t present : 1; - uint32_t writable : 1; - uint32_t belongsToUserProcess : 1; uint32_t writeThrough : 1; uint32_t isVolatile : 1; // disables the cpu cache uint32_t accessed : 1; @@ -30,13 +18,6 @@ } __attribute__((packed)) PageTableEntry; typedef struct { - uint32_t isPageAllocated[0x8000]; - uint32_t isPageAllocatedCoarse[0x400]; - uint32_t isPageTableInUse[0x20]; - uint32_t pageSearchStart; -} PagingInfo; - -typedef struct { uint32_t pageOffset : 12; uint32_t pageTableIndex : 10; uint32_t pageDirectoryIndex : 10; diff --git a/src/kernel/service/elf.h b/src/kernel/service/elf.h new file mode 100644 index 0000000..af9e01c --- /dev/null +++ b/src/kernel/service/elf.h @@ -0,0 +1,52 @@ +#ifndef ELF_H +#define ELF_H + +#include + +typedef struct { + uint32_t magic; + uint8_t is64BitFile; + uint8_t endianness; + uint8_t elfHeaderVersion; + uint8_t osABI; + uint32_t unused0, unused1; + uint16_t flags; + uint16_t instructionSet; + uint32_t elfVersion; + uint32_t entryPosition; + uint32_t programHeaderTablePosition; + uint32_t sectionHeaderTablePosition; + uint32_t architectureFlags; + uint16_t headerSize; + uint16_t programHeaderEntrySize; + uint16_t programHeaderEntryCount; + uint16_t sectionHeaderEntrySize; + uint16_t sectionHeaderEntryCount; + uint16_t sectionNamesHeaderTableIndex; +} ElfHeader; + +typedef struct { + uint16_t segmentType; + uint32_t dataOffset; + uint32_t virtualAddress; + uint32_t undefined; + uint32_t segmentFileSize; + uint32_t segmentMemorySize; + uint32_t flags; + uint32_t alignment; +} ProgramHeader; + +typedef struct { + uint32_t stringTableNameIndex; + uint32_t type; + uint32_t flags; + uint32_t virtualAddress; + uint32_t offset; + uint32_t size; + uint32_t link; + uint32_t info; + uint32_t alignment; + uint32_t entrySize; +} SectionHeader; + +#endif diff --git a/src/kernel/service/service.h b/src/kernel/service/service.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/kernel/service/service.h diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c new file mode 100644 index 0000000..f0c69e3 --- /dev/null +++ b/src/kernel/service/services.c @@ -0,0 +1,32 @@ +#include "elf.h" +#include "service.h" +#include +#include +#include + +PagingInfo testInfo; + +void loadElf(void *elfStart) { + // use this function ONLY to load the initrd/loader program! + ElfHeader *header = elfStart; + ProgramHeader *programHeader = + elfStart + header->programHeaderTablePosition; + PagingInfo *paging = &testInfo; + memset(paging, 0, sizeof(PagingInfo)); + void *data; + for (uint32_t i = 0; i < header->programHeaderEntryCount; i++) { + for (uint32_t page = 0; page < programHeader->segmentMemorySize; + page += 0x1000) { + data = malloc(0x1000); + memset(data, 0, 0x1000); + memcpy(elfStart + programHeader->dataOffset, data, + MIN(0x1000, programHeader->segmentFileSize - page)); + // sharePage(paging, data, + // elfStart + programHeader->dataOffset + page); + } + programHeader = (void *)programHeader + header->programHeaderEntrySize; + } + asm("mov %%eax, %0" ::"r"(U32(data))); + while (1) + ; +} diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index cb41d70..5731bda 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -3,11 +3,39 @@ #include +typedef struct { + uint32_t present : 1; + uint32_t writable : 1; + uint32_t belongsToUserProcess : 1; + uint32_t reserved : 2; + uint32_t accessed : 1; + uint32_t dirty : 1; + uint32_t reserved2 : 2; + uint32_t available : 3; + uint32_t pageTableID : 20; +} __attribute__((packed)) PageDirectoryEntry; + +typedef struct { + PageDirectoryEntry *pageDirectory; + uint32_t isPageTableInUse[0x20]; + uint32_t isPageAllocated[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 *getPage(); +extern void sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress); + +extern void *getPhysicalAddressKernel(void *address); #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h new file mode 100644 index 0000000..b746d66 --- /dev/null +++ b/src/kernel/include/service.h @@ -0,0 +1,6 @@ +#ifndef SERVICE_H +#define SERVICE_H + +extern void loadElf(void *fileData); + +#endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index ac89942..748a044 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -2,14 +2,18 @@ #define UTIL_H #include +#include #define U32(x) (uint32_t)(uintptr_t)(x) #define PTR(x) (void *)(uintptr_t)(x) #define NULL PTR(0) +#define MIN(x, y) (x < y ? x : y) + #define PAGE_COUNT(x) (((x - 1) / 4096) + 1) extern bool stringEquals(char *string1, char *string2); +extern void memcpy(void *source, void *destination, uint32_t size); #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 7fdcc82..9b91775 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -1,13 +1,15 @@ #include #include +#include #include void kernelMain(void *multibootInfo) { setupMemory(); - void *address = kernelMapPhysical(multibootInfo); + void *address = kernelMapMultiplePhysicalPages(multibootInfo, 4); uint32_t tarSize = 0; void *initrd = findInitrd(address, &tarSize); void *loaderProgram = findTarFile(initrd, tarSize, "initrd/loader"); + loadElf(loaderProgram); asm("mov %%eax, %0" ::"r"(loaderProgram)); while (1) ; diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c new file mode 100644 index 0000000..b6b9b40 --- /dev/null +++ b/src/kernel/memory/malloc.c @@ -0,0 +1,76 @@ +#include "malloc.h" +#include + +#define LOG2(X) ((unsigned)(64 - __builtin_clzll((X)) - 1)) + +AllocationData allocationData; + +void *reserveBlock(AllocationBlock *block, uint8_t coarse, uint8_t fine) { + block->allocatedFine[coarse] |= 1 << fine; + block->allocatedCoarse |= 1 << coarse; + for (uint8_t i = 0; i < 32; i++) { + if (block->allocatedFine[coarse] & 1 << i) { + continue; + } + block->allocatedCoarse &= ~(1 << coarse); + break; + } + return ((uint8_t *)block) + block->blockSize * (32 * coarse + fine); +} + +void *malloc(uint32_t size) { + uint32_t sizeBit = LOG2(size) + 1; + if (sizeBit > 10) { + return getPage(); + } + AllocationBlock *block = allocationData[sizeBit], *last = 0; + while (1) { + if (!block) { + block = getPage(); + memset(block, 0, 4096); + block->blockSize = 1 << sizeBit; + if (last) { + block->previous = last; + last->next = block; + } else { + allocationData[sizeBit] = block; + block->previous = (void *)(uintptr_t)sizeBit; + } + block->magic = ALLOCATION_MAGIC; + } + if (block->allocatedCoarse == ~0) { + goto end; + } + for (uint8_t coarse = 0; coarse < 32; coarse++) { + for (uint8_t fine = 0; fine < 32; fine++) { + if (block->allocatedFine[coarse] & (1 << fine)) { + continue; + } + return reserveBlock(block, coarse, fine); + } + } + end: + last = block; + block = block->next; + } +} + +void free(void *location) { + AllocationBlock *block = (void *)((uintptr_t)location & ~0xFFF); + if (block->magic != ALLOCATION_MAGIC) { + // freePage(location); + return; + } + uint16_t index = (uint16_t)((uintptr_t)location & 0xFFF) / block->blockSize; + uint8_t coarse = index / 32; + uint8_t fine = index % 32; + block->allocatedFine[coarse] &= ~(1 << fine); + block->allocatedCoarse &= ~(1 << coarse); + for (uint8_t i = 0; i < 32; i++) { + if (block->allocatedFine[coarse] & (1 << i)) { + continue; + } + block->allocatedCoarse |= 1 << coarse; + return; + } +} diff --git a/src/kernel/memory/malloc.h b/src/kernel/memory/malloc.h new file mode 100644 index 0000000..16e0c80 --- /dev/null +++ b/src/kernel/memory/malloc.h @@ -0,0 +1,20 @@ +#ifndef ALLOC_H +#define ALLOC_H + +#include + +#define ALLOCATION_MAGIC 0x44BB33DD + +typedef struct AllocationBlock { + uint8_t data[3948]; + uint32_t allocatedFine[32]; + uint32_t allocatedCoarse; + uint32_t blockSize; + struct AllocationBlock *next; + struct AllocationBlock *previous; + uint32_t magic; +} AllocationBlock; + +typedef AllocationBlock *AllocationData[12]; + +#endif diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index 0213f25..3bd35e9 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -2,13 +2,18 @@ #include #include -PageDirectoryEntry *kernelDirectory; -PageTableEntry *kernelCodePageTable, *kernelDataPageTable, *kernelUtilityPages; +PageTableEntry *kernelCodePageTable, *kernelDataPageTable; -PagingInfo *physicalPages, *kernelVirtualPages; +PagingInfo *kernelPhysicalPages, *kernelVirtualPages; + +void *temporaryPage; void reservePage(PagingInfo *info, uint32_t pageId); +void invalidatePage(uint32_t pageId) { + asm("invlpg (%0)" ::"r"(pageId << 12) : "memory"); +} + void *kernelGetVirtualAddress(void *_address) { uint32_t address = (uint32_t)(uintptr_t)_address; if (address < 0x100000) { @@ -23,52 +28,56 @@ return 0; } +void *mapTemporary(void *physical) { + kernelDataPageTable[3].targetAddress = U32(physical) >> 12; + kernelDataPageTable[3].writable = 1; + kernelDataPageTable[3].present = 1; + invalidatePage(0xFF803); + return temporaryPage; +} + void *getPhysicalAddress(void *address, PageDirectoryEntry *pageDirectory) { VirtualAddress *virtual = (void *)&address; uint32_t pageTableLocation = pageDirectory[virtual->pageDirectoryIndex].pageTableID; PageTableEntry *pageTable = PTR(pageTableLocation << 12); - pageTable = kernelGetVirtualAddress(pageTable); + pageTable = mapTemporary(pageTable); uint32_t pageBase = pageTable[virtual->pageTableIndex].targetAddress; return PTR(pageBase << 12 | virtual->pageOffset); } -void mapDirectoryEntry(PageDirectoryEntry *directory, uint32_t pageTableIndex, - PageTableEntry *pageTable, PagingInfo *pagingInfo) { - directory[pageTableIndex].pageTableID = - U32(getPhysicalAddress(pageTable, directory)) >> 12; - directory[pageTableIndex].writable = 1; - directory[pageTableIndex].present = 1; - pagingInfo->isPageTableInUse[pageTableIndex / 32] |= - 1 << (pageTableIndex % 32); +void *getPhysicalAddressKernel(void *address) { + return getPhysicalAddress(address, kernelVirtualPages->pageDirectory); } +uint32_t findPage(PagingInfo *info); +void mapPage(PagingInfo *info, void *physical, void *virtual); + void reservePagesUntilPhysical(uint32_t endPageId) { void *buffer = (void *)0xFF800000; - kernelDirectory = buffer; - memset(kernelDirectory, 0, 0xFF8); - buffer += 0x1000; - kernelCodePageTable = buffer; + void *pageDirectory = buffer; + memset(pageDirectory, 0, 0xFF8); buffer += 0x1000; kernelDataPageTable = buffer; buffer += 0x1000; - kernelUtilityPages = buffer; + kernelCodePageTable = buffer; buffer += 0x1000; - physicalPages = buffer; + temporaryPage = buffer; + buffer += 0x1000; + kernelPhysicalPages = buffer; buffer += sizeof(PagingInfo); kernelVirtualPages = buffer; buffer += sizeof(PagingInfo); - memset(physicalPages, 0, 2 * sizeof(PagingInfo)); + memset(kernelPhysicalPages, 0, 2 * sizeof(PagingInfo)); for (uint32_t i = 0; i < endPageId; i++) { - reservePage(physicalPages, i); + reservePage(kernelPhysicalPages, i); } for (uint32_t i = 0; i < 0x800; i++) { reservePage(kernelVirtualPages, i + 0xFF800); } - memset(kernelUtilityPages, 0, 0x1000); - mapDirectoryEntry(kernelDirectory, 0, kernelUtilityPages, - kernelVirtualPages); - physicalPages->pageSearchStart = endPageId; + kernelPhysicalPages->pageSearchStart = endPageId; + kernelVirtualPages->pageSearchStart = 0; + kernelVirtualPages->pageDirectory = pageDirectory; } void reservePage(PagingInfo *info, uint32_t pageId) { @@ -115,12 +124,12 @@ uint32_t physicalPageStart = U32(address) >> 12; uint32_t virtualPageStart = findMultiplePages(kernelVirtualPages, size); for (uint32_t i = 0; i < size; i++) { - reservePage(physicalPages, physicalPageStart + i); + reservePage(kernelPhysicalPages, physicalPageStart + i); reservePage(kernelVirtualPages, virtualPageStart + i); - kernelUtilityPages[virtualPageStart + i].targetAddress = - physicalPageStart + i; - kernelUtilityPages[virtualPageStart + i].writable = 1; - kernelUtilityPages[virtualPageStart + i].present = 1; + } + for (uint32_t i = 0; i < size; i++) { + mapPage(kernelVirtualPages, PTR((physicalPageStart + i) << 12), + PTR((virtualPageStart + i) << 12)); } return PTR((virtualPageStart << 12) + (U32(address) & 0xFFF)); } @@ -128,3 +137,42 @@ void *kernelMapPhysical(void *address) { return kernelMapMultiplePhysicalPages(address, 1); } + +void mapPage(PagingInfo *info, void *physical, void *virtual) { + VirtualAddress *address = (void *)&virtual; + PageDirectoryEntry *directory = info->pageDirectory; + if (!directory[address->pageDirectoryIndex].present) { + uint32_t newPageTable = findPage(kernelPhysicalPages); + reservePage(kernelPhysicalPages, newPageTable); + void *temporary = mapTemporary(PTR(newPageTable << 12)); + memset(temporary, 0, 0x1000); + directory[address->pageDirectoryIndex].pageTableID = newPageTable; + directory[address->pageDirectoryIndex].present = 1; + directory[address->pageDirectoryIndex].writable = 1; + } + void *pageTablePhysical = + PTR(directory[address->pageDirectoryIndex].pageTableID << 12); + void *temporary = mapTemporary(pageTablePhysical); + PageTableEntry *pageTable = temporary; + pageTable[address->pageTableIndex].targetAddress = U32(physical) >> 12; + pageTable[address->pageTableIndex].present = 1; + pageTable[address->pageTableIndex].writable = 1; + invalidatePage(U32(virtual) >> 12); +} + +void *getPage() { + uint32_t physical = findPage(kernelPhysicalPages); + reservePage(kernelPhysicalPages, physical); + uint32_t virtual = findPage(kernelVirtualPages); + reservePage(kernelVirtualPages, virtual); + mapPage(kernelVirtualPages, PTR(physical << 12), PTR(virtual << 12)); + return PTR(virtual << 12); +} + +void sharePage(PagingInfo *destination, void *sourceAddress, + void *destinationAddress) { + PagingInfo *source = kernelVirtualPages; + void *physicalSource = + getPhysicalAddress(sourceAddress, source->pageDirectory); + mapPage(destination, physicalSource, destinationAddress); +} diff --git a/src/kernel/memory/paging.h b/src/kernel/memory/paging.h index 208f670..c6c3e10 100644 --- a/src/kernel/memory/paging.h +++ b/src/kernel/memory/paging.h @@ -7,18 +7,6 @@ uint32_t present : 1; uint32_t writable : 1; uint32_t belongsToUserProcess : 1; - uint32_t reserved : 2; - uint32_t accessed : 1; - uint32_t dirty : 1; - uint32_t reserved2 : 2; - uint32_t available : 3; - uint32_t pageTableID : 20; -} __attribute__((packed)) PageDirectoryEntry; - -typedef struct { - uint32_t present : 1; - uint32_t writable : 1; - uint32_t belongsToUserProcess : 1; uint32_t writeThrough : 1; uint32_t isVolatile : 1; // disables the cpu cache uint32_t accessed : 1; @@ -30,13 +18,6 @@ } __attribute__((packed)) PageTableEntry; typedef struct { - uint32_t isPageAllocated[0x8000]; - uint32_t isPageAllocatedCoarse[0x400]; - uint32_t isPageTableInUse[0x20]; - uint32_t pageSearchStart; -} PagingInfo; - -typedef struct { uint32_t pageOffset : 12; uint32_t pageTableIndex : 10; uint32_t pageDirectoryIndex : 10; diff --git a/src/kernel/service/elf.h b/src/kernel/service/elf.h new file mode 100644 index 0000000..af9e01c --- /dev/null +++ b/src/kernel/service/elf.h @@ -0,0 +1,52 @@ +#ifndef ELF_H +#define ELF_H + +#include + +typedef struct { + uint32_t magic; + uint8_t is64BitFile; + uint8_t endianness; + uint8_t elfHeaderVersion; + uint8_t osABI; + uint32_t unused0, unused1; + uint16_t flags; + uint16_t instructionSet; + uint32_t elfVersion; + uint32_t entryPosition; + uint32_t programHeaderTablePosition; + uint32_t sectionHeaderTablePosition; + uint32_t architectureFlags; + uint16_t headerSize; + uint16_t programHeaderEntrySize; + uint16_t programHeaderEntryCount; + uint16_t sectionHeaderEntrySize; + uint16_t sectionHeaderEntryCount; + uint16_t sectionNamesHeaderTableIndex; +} ElfHeader; + +typedef struct { + uint16_t segmentType; + uint32_t dataOffset; + uint32_t virtualAddress; + uint32_t undefined; + uint32_t segmentFileSize; + uint32_t segmentMemorySize; + uint32_t flags; + uint32_t alignment; +} ProgramHeader; + +typedef struct { + uint32_t stringTableNameIndex; + uint32_t type; + uint32_t flags; + uint32_t virtualAddress; + uint32_t offset; + uint32_t size; + uint32_t link; + uint32_t info; + uint32_t alignment; + uint32_t entrySize; +} SectionHeader; + +#endif diff --git a/src/kernel/service/service.h b/src/kernel/service/service.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/kernel/service/service.h diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c new file mode 100644 index 0000000..f0c69e3 --- /dev/null +++ b/src/kernel/service/services.c @@ -0,0 +1,32 @@ +#include "elf.h" +#include "service.h" +#include +#include +#include + +PagingInfo testInfo; + +void loadElf(void *elfStart) { + // use this function ONLY to load the initrd/loader program! + ElfHeader *header = elfStart; + ProgramHeader *programHeader = + elfStart + header->programHeaderTablePosition; + PagingInfo *paging = &testInfo; + memset(paging, 0, sizeof(PagingInfo)); + void *data; + for (uint32_t i = 0; i < header->programHeaderEntryCount; i++) { + for (uint32_t page = 0; page < programHeader->segmentMemorySize; + page += 0x1000) { + data = malloc(0x1000); + memset(data, 0, 0x1000); + memcpy(elfStart + programHeader->dataOffset, data, + MIN(0x1000, programHeader->segmentFileSize - page)); + // sharePage(paging, data, + // elfStart + programHeader->dataOffset + page); + } + programHeader = (void *)programHeader + header->programHeaderEntrySize; + } + asm("mov %%eax, %0" ::"r"(U32(data))); + while (1) + ; +} diff --git a/src/kernel/util/memutil.c b/src/kernel/util/memutil.c new file mode 100644 index 0000000..bfa1bc6 --- /dev/null +++ b/src/kernel/util/memutil.c @@ -0,0 +1,8 @@ +#include + +void memcpy(void *source, void *destination, uint32_t size) { + uint8_t *src = source, *dest = destination; + for (uint32_t i = 0; i < size; i++) { + dest[i] = src[i]; + } +}