diff --git a/src/kernel/arch/x86/consts.h b/src/kernel/arch/x86/consts.h index bd1b97e..07f3c07 100644 --- a/src/kernel/arch/x86/consts.h +++ b/src/kernel/arch/x86/consts.h @@ -17,4 +17,10 @@ #define PAGE_BIT_WRITABLE 2 #define PAGE_BIT_USER 4 -#endif \ No newline at end of file +#define PAGE_PRESENT(p) ((p) & (PAGE_BIT_PRESENT)) + +#define PAGE_SIZE 4096 + +#define ROUND_UP_POT(i, n) (((i) + ((n) - 1)) & ~((n) - 1)) + +#endif diff --git a/src/kernel/arch/x86/scheduler.c b/src/kernel/arch/x86/scheduler.c index dea82e1..926fadc 100644 --- a/src/kernel/arch/x86/scheduler.c +++ b/src/kernel/arch/x86/scheduler.c @@ -21,7 +21,7 @@ uint32_t scheduler_Tick; void klogs(const char *str); void klogc(int c); -static void klogp(void *p) { +void klogp(void *p) { static char hex[16]="0123456789ABCDEF"; uintptr_t i = (uintptr_t) p; diff --git a/src/kernel/arch/x86/vpm.c b/src/kernel/arch/x86/vpm.c index 8b4dcfc..42d1253 100644 --- a/src/kernel/arch/x86/vpm.c +++ b/src/kernel/arch/x86/vpm.c @@ -2,49 +2,57 @@ #include"ppm.h" #include"mem.h" +#include"consts.h" -extern void *_kernel_end; +static void invlpg(uint32_t virtaddr) { + asm volatile("invlpg %0" : : "m"(*(char*)virtaddr) : "memory"); +} -void set_temporary_mapping(uint32_t addr) { +static void set_temporary_mapping(uint32_t addr) { if((addr & 0xFFF) != 0) asm volatile("xchgw %bx, %bx"); *(volatile uint32_t*) 0xFFFFFFF8 = addr | 3; asm volatile("invlpg 0xFFFFE000" : : : "memory"); } -static uint32_t nextAllocs[2] = {[VPM_KERNEL] = 0, [VPM_USER] = 1 * 1024 * 1024 * 1024}; +static uint32_t spaceBoundaries[2] = {[VPM_KERNEL] = 4096, [VPM_USER] = 1 * 1024 * 1024 * 1024}; void vpm_init(uint32_t kernelEnd) { - nextAllocs[VPM_KERNEL] = (kernelEnd + 4095) & ~4095; + //spaceBoundaries[VPM_KERNEL] = (kernelEnd + 4095) & ~4095; } -/* TODO: Make better. */ -uint32_t vpm_find_free(uint32_t addrspace, AllocationOwner owner, size_t lenBytes) { - size_t len = (lenBytes + 4095) / 4096; +/* This is a linear search. Improve? */ +uint32_t vpm_find_free(uint32_t addrspace, AllocationOwner owner, size_t len) { + len = ROUND_UP_POT(len, PAGE_SIZE); - uint32_t ret = nextAllocs[owner]; - for(size_t i = 0; i < len;) { - uint32_t pdeid = (ret + i * 4096) >> 22; - uint32_t pteid = ((ret + i * 4096) >> 12) & 1023; - - set_temporary_mapping(addrspace); - - volatile uint32_t *pde = &((volatile uint32_t*) 0xFFFFE000)[pdeid]; - if((*pde & 1) == 0) { - i += 4096; - } else { - set_temporary_mapping(*pde & ~0xFFF); + for(uint32_t attempt = spaceBoundaries[owner]; attempt != 0;) { + for(size_t i = 0; i < len;) { + uint32_t pdeid = (attempt + i) >> 22; + uint32_t pteid = ((attempt + i) >> 12) & 1023; - if((((volatile uint32_t*) 0xFFFFE000)[pteid] & 1) == 0) { - i++; + set_temporary_mapping(addrspace); + + volatile uint32_t *pde = &((volatile uint32_t*) 0xFFFFE000)[pdeid]; + if(!PAGE_PRESENT(*pde)) { + i += PAGE_SIZE * 1024 * 1024; // 4MB } else { - ret += (i + 1) * 4096; - i = 0; + set_temporary_mapping((*pde) & ~0xFFF); + + volatile uint32_t *pte = &((volatile uint32_t*) 0xFFFFE000)[pteid]; + + if(!PAGE_PRESENT(*pte)) { + i += PAGE_SIZE; + } else { + attempt += i + PAGE_SIZE; + goto try_next; + } } } - } + return attempt; +try_next: + } - return ret; + return 0; } /* If phys is -1, map to uncontiguous physical pages anywhere, else map contiguous span of physical memory. */ @@ -99,8 +107,8 @@ void *vpm_map(uint32_t addrspace, AllocationOwner owner, uint32_t virt, uint32_t *pte |= 3 | (owner == VPM_USER ? 4 : 0); if(thisspace == addrspace) { - //~ asm volatile("xchg %bx, %bx"); - asm volatile("invlpg %0" : : "m"(*(char*) (virt + i * 4096)) : "memory"); + invlpg(virt + i * 4096); + //asm volatile("invlpg %0" : : "m"(*(char*) (virt + i * 4096)) : "memory"); } } @@ -164,7 +172,8 @@ int vpm_double_map(uint32_t cr3a, uint32_t cr3b, uint32_t *va, uint32_t *vb, uin *pte = backend | 3 | 4; if(thisspace == cr3a) { - asm volatile("invlpg %0" : : "m"(*(char*) (*va + i * 4096)) : "memory"); + invlpg(*va + i * 4096); + //asm volatile("invlpg %0" : : "m"(*(char*) (*va + i * 4096)) : "memory"); } } @@ -193,7 +202,8 @@ int vpm_double_map(uint32_t cr3a, uint32_t cr3b, uint32_t *va, uint32_t *vb, uin *pte = backend | 3 | 4; if(thisspace == cr3b) { - asm volatile("invlpg %0" : : "m"(*(char*) (*vb + i * 4096)) : "memory"); + invlpg(*vb + i * 4096); + //asm volatile("invlpg %0" : : "m"(*(char*) (*vb + i * 4096)) : "memory"); } } } @@ -262,7 +272,8 @@ void vpm_unmap(uint32_t cr3, uint32_t virt, size_t len) { ((volatile uint32_t*) 0xFFFFE000)[pteid] = 0; if(thisspace == cr3) { - asm volatile("invlpg %0" : : "m"(*(char*) (virt + i * 4096)) : "memory"); + invlpg(virt + i * 4096); + //asm volatile("invlpg %0" : : "m"(*(char*) (virt + i * 4096)) : "memory"); } } } diff --git a/src/kernel/arch/x86/vpm.h b/src/kernel/arch/x86/vpm.h index 63b4816..71639ec 100644 --- a/src/kernel/arch/x86/vpm.h +++ b/src/kernel/arch/x86/vpm.h @@ -12,8 +12,6 @@ typedef enum { VPM_KERNEL, VPM_USER } AllocationOwner; -void set_temporary_mapping(uint32_t addr); - uint32_t vpm_find_free(uint32_t addrspace, AllocationOwner owner, size_t len); void *vpm_map(uint32_t cr3, AllocationOwner owner, uint32_t virt, uint32_t phys, size_t len); uint32_t vpm_create_space(); @@ -21,4 +19,4 @@ void vpm_set_space(uint32_t cr3); uint32_t vpm_get_phys(uint32_t cr3, uint32_t); void vpm_unmap(uint32_t cr3, uint32_t virt, size_t len); -#endif \ No newline at end of file +#endif