diff --git a/Makefile b/Makefile index cc8a534..381e871 100644 --- a/Makefile +++ b/Makefile @@ -47,4 +47,4 @@ $(BUILD_DIR)/$(ISO_NAME): $(BUILD_DIR)/$(K_BIN_NAME) grub.cfg grub-mkrescue -o $(BUILD_DIR)/$(ISO_NAME) $(BUILD_DIR)/iso run: all - qemu-system-x86_64 $(BUILD_DIR)/$(ISO_NAME) -serial stdio + qemu-system-x86_64 $(BUILD_DIR)/$(ISO_NAME) -serial stdio -m 4G diff --git a/src/arch/amd64/boot.S b/src/arch/amd64/boot.S index 447ac2f..6482d79 100644 --- a/src/arch/amd64/boot.S +++ b/src/arch/amd64/boot.S @@ -1,9 +1,10 @@ global start -global pml4_list -global init_pdpt -global init_pd -global init_pt +global kernel_pml4 +global kernel_pdpt_0 +global kernel_pd_0 +global kernel_pt_0 global paging_pt +global bootstrap_pt extern kmain extern amd64_shim bits 32 @@ -25,15 +26,17 @@ mb_end: section .bss align 4096 -pml4_list: ; reserve memory for initial 512 pml4 entires +kernel_pml4: ; reserve memory for initial 512 pml4 entires resb 4096 -init_pdpt: ; reserve memory for initial 512 pdpt entires +kernel_pdpt_0: ; reserve memory for initial 512 pdpt entires resb 4096 -init_pd: ; reserve memory for initial 512 pd entries +kernel_pd_0: ; reserve memory for initial 512 pd entries resb 4096 -init_pt: ; reserve memory for initial 512 pt entries +kernel_pt_0: ; reserve memory for initial 512 pt entries resb 4096 -paging_pt: ; reserve memory for 512 paging reserved pt entires +paging_pt: ; reserve pages for pager mappings + resb 4096 +bootstrap_pt: ; reserve pages to bootstrap pager resb 4096 align 16 @@ -85,6 +88,7 @@ start: mov esp, stack_end mov ebp, stack_end + push DWORD 0 push ebx mov edi, 0x1000 @@ -93,13 +97,13 @@ start: mov ecx, 4096 rep stosd mov edi, cr3 - ; FIXME: Update boot.S to point base of paging to pml4e_list, see above - mov DWORD [edi], 0x2003 ; Set the uint32_t at the destination index to 0x2003. - add edi, 0x1000 ; Add 0x1000 to the destination index. - mov DWORD [edi], 0x3003 ; Set the uint32_t at the destination index to 0x3003. - add edi, 0x1000 ; Add 0x1000 to the destination index. - mov DWORD [edi], 0x4003 ; Set the uint32_t at the destination index to 0x4003. - add edi, 0x1000 ; Add 0x1000 to the destination index. + + mov DWORD [edi], kernel_pdpt_0 + 3 ; Set the uint32_t at the destination index to 0x2003. + mov edi, kernel_pdpt_0 ; Add 0x1000 to the destination index. + mov DWORD [edi], kernel_pd_0 + 3 ; Set the uint32_t at the destination index to 0x3003. + mov edi, kernel_pd_0 ; Add 0x1000 to the destination index. + mov DWORD [edi], kernel_pt_0 + 3 ; Set the uint32_t at the destination index to 0x4003. + mov edi, kernel_pt_0 ; Add 0x1000 to the destination index. mov ebx, 0x00000003 ; Set the B-register to 0x00000003. mov ecx, 512 ; Set the C-register to 512. @@ -132,6 +136,7 @@ start: bits 64 code64: + pop rdi call amd64_shim mov rdi, rax call kmain diff --git a/src/arch/amd64/mboot.c b/src/arch/amd64/mboot.c index a6ee465..fbaaa92 100644 --- a/src/arch/amd64/mboot.c +++ b/src/arch/amd64/mboot.c @@ -1,24 +1,28 @@ #include "mboot.h" +#include "serial.h" #include #include -static void read_cmdline(struct mboot_info *info, struct mboot_tag *tag, char *data, uint8_t len) { +static void read_cmdline(struct mboot_tag *tag, char *data, uint8_t len) { if (len >= CMDLINE_MAX) len = CMDLINE_MAX; // truncate :( memcpy(tag->data.cmdline, data, len); tag->data.cmdline[len] = '\0'; - info->tags[MBOOT_CMDLINE] = *tag; } -static void read_xsdp(struct mboot_info *info, struct mboot_tag *tag, char *data) { +static void read_memorymap(struct mboot_tag *tag, uint64_t size, uint32_t *data) { + tag->data.memory_map = (struct memory_map *) data; + tag->data.memory_map->size = size; +} + +static void read_xsdp(struct mboot_tag *tag, char *data) { tag->data.rootsdp = (void *) data; - info->tags[MBOOT_XSDP] = *tag; } static uint32_t *read_tag(struct mboot_info *info, uint32_t *data) { struct mboot_tag tag; - tag.type = ((uint16_t*)data)[0]; + tag.type = *((uint16_t *)data); tag.size = data[1]; tag.valid = 1; @@ -26,15 +30,20 @@ static uint32_t *read_tag(struct mboot_info *info, uint32_t *data) { switch (tag.type) { case MBOOT_CMDLINE: - read_cmdline(info, &tag, (char *)(data + 2), data_len); + read_cmdline(&tag, (char *)(data + 2), data_len); + break; + case MBOOT_MEMORYMAP: + read_memorymap(&tag, tag.size, data + 2); break; case MBOOT_XSDP: - read_xsdp(info, &tag, (char *) (data + 2)); + read_xsdp(&tag, (char *) (data + 2)); break; default: break; } + info->tags[tag.type] = tag; + if(tag.size % 8 != 0) { tag.size += 8 - (tag.size % 8); } @@ -42,12 +51,13 @@ static uint32_t *read_tag(struct mboot_info *info, uint32_t *data) { return data + tag.size / sizeof(uint32_t); } -struct mboot_info mboot_load_info(void *mboot_info) { +struct mboot_info mboot_load_info(const void *mboot_info) { struct mboot_info info = {0}; uint32_t* data = (uint32_t*) mboot_info; info.total_size = *data++; info.reserved = *data++; + while((uint8_t*) data < (uint8_t*) mboot_info + info.total_size) { data = read_tag(&info, data); diff --git a/src/arch/amd64/mboot.h b/src/arch/amd64/mboot.h index 2d8c53c..6e407d5 100644 --- a/src/arch/amd64/mboot.h +++ b/src/arch/amd64/mboot.h @@ -25,14 +25,14 @@ enum mboot_tag_type { struct mboot_info { uint32_t total_size; uint32_t reserved; - struct mboot_tag tags[21]; + struct mboot_tag tags[22]; }; /** * Loads the multi boot information * @param mboot_info - the pointer passed from multiboot2 */ -struct mboot_info mboot_load_info(void *mboot_info); +struct mboot_info mboot_load_info(const void *mboot_info); /** * Gets a tag from multiboot diff --git a/src/arch/amd64/paging.c b/src/arch/amd64/paging.c index 3140a2a..836f602 100644 --- a/src/arch/amd64/paging.c +++ b/src/arch/amd64/paging.c @@ -7,18 +7,9 @@ #include #include +#include "paging.h" #include "bindings.h" -#define F_PRESENT 0x001 -#define F_WRITEABLE 0x002 -#define F_UNPRIVILEGED 0x004 -#define F_WRITETHROUGH 0x008 -#define F_CACHEDISABLE 0x010 -#define F_ACCESSED 0x020 -#define F_DIRTY 0x040 -#define F_MEGABYTE 0x080 -#define F_GLOBAL 0x100 - // PAGE MAP LEVEL 4 ENTRY struct pml4e { uint64_t flags : 6; @@ -61,19 +52,19 @@ struct pte { }; // bss segment, can write to -extern struct pml4e pml4_list[512]; -extern struct pdpte init_pdpt[512]; -extern struct pde init_pd[512]; -extern struct pte init_pt[512]; +extern struct pml4e kernel_pml4[512]; +extern struct pdpte kernel_pdpt_0[512]; +extern struct pde kernel_pd_0[512]; +extern struct pte bootstrap_pt[512]; extern struct pte paging_pt[512]; // paging_pt should NEVER be outside of this file, NEVER i say // paged address to read page tables // the structures are not gurenteed to be ident mapped // map them here with map_(phys_addr) before useing structures -static struct pdpte *pdpt_mapped = (void *) (uintptr_t) 0x1000; -static struct pdpte *pd_mapped = (void *) (uintptr_t) 0x2000; -static struct pdpte *pt_mapped = (void *) (uintptr_t) 0x3000; -void *addr_mapped = (void *) (uintptr_t) 0x4000; +static struct pdpte *pdpt_mapped = (void *) (uintptr_t) 0x201000; +static struct pdpte *pd_mapped = (void *) (uintptr_t) 0x202000; +static struct pdpte *pt_mapped = (void *) (uintptr_t) 0x203000; +void *addr_mapped = (void *) (uintptr_t) 0x204000; static inline void invlpg(void *addr) { __asm volatile("invlpg (%0)" ::"r" (addr) : "memory"); @@ -172,6 +163,7 @@ int map_page(struct pml4e *pml4, void *virt_addr, void *phys_addr, unsigned int map_pt(__pt); pt_mapped[pt_offset].flags = F_PRESENT | flags; pt_mapped[pt_offset].address = (((uint64_t)phys_addr) >> 12); + invlpg(virt_addr); return 0; } @@ -236,51 +228,52 @@ done: } void paging_init(void) { - memset(pml4_list, 0, 4096); - pml4_list[0].flags = F_PRESENT | F_WRITEABLE; - pml4_list[0].address = (uint64_t)init_pdpt >> 12; + + kernel_pml4[0].flags = F_PRESENT | F_WRITEABLE; + kernel_pml4[0].address = (uint64_t)(&kernel_pdpt_0) >> 12; + + kernel_pdpt_0[0].flags = F_PRESENT | F_WRITEABLE; + kernel_pdpt_0[0].address = (uint64_t)(&kernel_pd_0) >> 12; + + kernel_pd_0[1].flags = F_PRESENT | F_WRITEABLE; + kernel_pd_0[1].address = (uint64_t)(&paging_pt) >> 12; + kernel_pd_0[2].flags = F_PRESENT | F_WRITEABLE; + kernel_pd_0[2].address = (uint64_t)(&bootstrap_pt) >> 12; - memset(init_pdpt, 0, 4096); - init_pdpt[0].flags = F_PRESENT | F_WRITEABLE; - init_pdpt[0].address = (uint64_t)init_pd >> 12; - - memset(pml4_list, 0, 4096); - init_pd[0].flags = F_PRESENT | F_WRITEABLE; - init_pd[0].address = (uint64_t)paging_pt >> 12; - init_pd[1].flags = F_PRESENT | F_WRITEABLE; - init_pd[1].address = (uint64_t)init_pt >> 12; - - memset(init_pt, 0, 4096); - memset(paging_pt, 0, 4096); + memset(&paging_pt, 0, 4096); + memset(&bootstrap_pt, 0, 4096); } static inline void *page_align(void *addr) { uintptr_t a = (uintptr_t) addr; - a += PAGE_SIZE + 1; + a += PAGE_SIZE - 1; a /= PAGE_SIZE; + a *= PAGE_SIZE; return (void *) a; } void *mmap(void *addr, size_t len) { - len += (uintptr_t)addr % PAGE_SIZE; - int pages = (len + PAGE_SIZE - 1) / PAGE_SIZE; + len += (long)addr % PAGE_SIZE; + long pages = (len + PAGE_SIZE - 1) / PAGE_SIZE; void *virt = virtaddr_alloc(pages); - if (virt == NULL) + if (virt == NULL) { return NULL; + } void *phys = page_align(addr); for (long i = 0; i < pages; i++) { void *virt_temp = (char *)virt + (i * PAGE_SIZE); void *phys_temp = (char *)phys + (i * PAGE_SIZE); - map_page(pml4_list, virt_temp, phys_temp, F_WRITEABLE); + map_page(kernel_pml4, virt_temp, phys_temp, F_WRITEABLE); } - return addr; + map_page(kernel_pml4, virt, (void*)0x23443, F_WRITEABLE); + return virt; } void unmap(void *addr) { long pages = virtaddr_free(addr); for (long i = 0; i < pages; i++) { void *virt = (char *)addr + (i * PAGE_SIZE); - unmap_page(pml4_list, virt); + unmap_page(kernel_pml4, virt); } } @@ -296,7 +289,7 @@ void *alloc_pages(int count) { for (int i = 0; i < count; i++) { void *virt_temp = (char *)virt + (i * PAGE_SIZE); void *phys_temp = (char *)phys + (i * PAGE_SIZE); - map_page(pml4_list, virt_temp, phys_temp, F_WRITEABLE); + map_page(kernel_pml4, virt_temp, phys_temp, F_WRITEABLE); } return virt; } @@ -307,7 +300,7 @@ void free_page(void *virt) { return; for (long i = 0; i < pages; i++) { void *virt_temp = (char *)virt + (i * PAGE_SIZE); - unmap_page(pml4_list, virt_temp); + unmap_page(kernel_pml4, virt_temp); } } @@ -318,3 +311,11 @@ void memory_lock(void) { void memory_unlock(void) { sti(); } + +int kmap_page(void *virt_addr, void *phys_addr, unsigned int flags) { + return map_page(kernel_pml4, virt_addr, phys_addr, flags); +} + +int kunmap_page(void *virt_addr) { + return unmap_page(kernel_pml4, virt_addr); +} diff --git a/src/arch/amd64/paging.h b/src/arch/amd64/paging.h new file mode 100644 index 0000000..b32c376 --- /dev/null +++ b/src/arch/amd64/paging.h @@ -0,0 +1,16 @@ +#pragma once + +#define F_PRESENT 0x001 +#define F_WRITEABLE 0x002 +#define F_UNPRIVILEGED 0x004 +#define F_WRITETHROUGH 0x008 +#define F_CACHEDISABLE 0x010 +#define F_ACCESSED 0x020 +#define F_DIRTY 0x040 +#define F_MEGABYTE 0x080 +#define F_GLOBAL 0x100 + +int kmap_page(void *virt_addr, void *phys_addr, unsigned int flags); +int kunmap_page(void *virt_addr); + +void paging_init(void); diff --git a/src/arch/amd64/shim.c b/src/arch/amd64/shim.c index dcd37bf..4afa6d2 100644 --- a/src/arch/amd64/shim.c +++ b/src/arch/amd64/shim.c @@ -4,23 +4,17 @@ #include #include +#include "paging.h" #include "mboot.h" static struct boot_info boot_info; // entry point for amd64 void* amd64_shim(void *mboot_data_ptr) { - //struct pml4e *pml4 = (struct pml4e *)0x1000; - //struct pdpte *pdpt = (struct pdpte *)0x2000; - //struct pde *pd = (struct pde *)0x3000; - //struct pte *pt = (struct pte *)0x4000; - //pd[1].flags = F_PRESENT | F_WRITEABLE; - //pd[1].address = ((uint64_t)pt) >> 12; - //map_page(pml4, (void *)0x80000000, (void *)0xB8002, F_WRITEABLE); - //__asm("invlpg 0x200000"); - //void *ret; - //find_phys_addr(pml4, (void *)0x80000000, &ret); - //return ret; + serial_init(); + paging_init(); + + kmap_page(mboot_data_ptr, mboot_data_ptr, F_WRITEABLE); struct mboot_info mboot_info; mboot_info = mboot_load_info(mboot_data_ptr); diff --git a/src/kmain.c b/src/kmain.c index 42d8ea5..4bd2190 100644 --- a/src/kmain.c +++ b/src/kmain.c @@ -10,6 +10,7 @@ void kmain(struct boot_info *info) { memory_init(info->map); //*(char*)(0xB8002 + 0x20'0000) = 'd'; itoa((long)info, buf, 16); + itoa(*(long*)info, buf, 16); //fb_init(1024, 768); serial_out_str(buf); } diff --git a/src/memory/physalloc.c b/src/memory/physalloc.c index b8eada6..7414d2e 100644 --- a/src/memory/physalloc.c +++ b/src/memory/physalloc.c @@ -7,8 +7,9 @@ #include #include -extern uintptr_t kernel_start; -extern uintptr_t kernel_end; +extern char kernel_start; +extern char kernel_end; +#define kaddr(addr) ((uintptr_t)(&addr)) // between memory_start and kernel_start will be the bitmap static uintptr_t memory_start = 0; @@ -113,9 +114,9 @@ void free_phys_pages(void *ptr, int pages) { static bool segment_invalid(const struct memory_segment *segment) { if (segment->type != 1) return false; - if (segment->addr < kernel_start) return false; + if (segment->addr < kaddr(kernel_start)) return false; if (segment->addr + segment->len < memory_start) return false; - if (segment->addr + segment->len < kernel_start) return false; + if (segment->addr + segment->len < kaddr(kernel_start)) return false; return true; } @@ -127,7 +128,7 @@ static struct memory_area segment_to_area(const struct memory_segment *segment) if (memory_start) start = memory_start; else - start = kernel_end; + start = kaddr(kernel_end); if (segment->addr < start) { addr = start; @@ -144,7 +145,7 @@ static struct memory_area segment_to_area(const struct memory_segment *segment) } static uintptr_t page_align(uintptr_t ptr) { - return ptr + PAGE_SIZE - 1 / PAGE_SIZE; + return (ptr + PAGE_SIZE - 1) / PAGE_SIZE * PAGE_SIZE; } void memory_init(struct memory_map *map) { @@ -165,7 +166,7 @@ void memory_init(struct memory_map *map) { struct memory_segment *segment = &map->entries[0]; int segment_count = 0; - + for(; (uintptr_t) segment < end; segment++) { if (segment_invalid(segment)) continue; @@ -180,15 +181,17 @@ void memory_init(struct memory_map *map) { //HACK: terrible hack bad bad bad bad long bitmap_size = bitmap_pages * PAGE_SIZE; - bitmap = (uint64_t *) page_at(page_count - bitmap_pages); + bitmap = (uint64_t *) page_align(kaddr(kernel_end)); + char buf[20]; long page_area_size = segment_count * sizeof(struct memory_area); char *page_area_addr = (char *)bitmap + bitmap_size; - bitmap = mmap(bitmap, bitmap_size); + ltoa((long)bitmap, buf, 16); + memset(bitmap, 0, 12); memset(bitmap, 0, bitmap_size); - memory_start = page_align(kernel_end + bitmap_size + page_area_size); + memory_start = page_align(kaddr(kernel_end) + bitmap_size + page_area_size); page_area_addr = mmap(page_area_addr, page_area_size); page_start = (struct memory_area *) page_area_addr; diff --git a/src/memory/virtalloc.c b/src/memory/virtalloc.c index b8135ef..f8d8169 100644 --- a/src/memory/virtalloc.c +++ b/src/memory/virtalloc.c @@ -26,7 +26,7 @@ static struct addr_node *alloc_node(void) { } else { struct addr_node *node = &nodes[bss_nodes]; bss_nodes += 1; - node->is_bss = false; + node->is_bss = true; return node; } return NULL; @@ -39,8 +39,8 @@ static void free_node(struct addr_node *node) { void virtaddr_init(void) { struct addr_node init = { - .start = 0, - .end = UINT64_MAX, + .start = 0x400000, // third page table + .end = 0x1000000000000, // 48bit memory address max .next = NULL, .prev = NULL, .is_alloc = false, @@ -53,6 +53,10 @@ void virtaddr_init(void) { void *virtaddr_alloc(int n_pages) { + + if (n_pages < 1) + return NULL; + long n_length = n_pages * PAGE_SIZE; struct addr_node *node = start_node; @@ -64,17 +68,19 @@ void *virtaddr_alloc(int n_pages) { long length = node->end - node->start; if (length >= n_length) { struct addr_node *new = alloc_node(); - if (node == NULL) + if (node == NULL) { return NULL; - new->next = node; - node->prev = new; + } if (node->prev != NULL) { node->prev->next = new; } + new->next = node; + node->prev = new; new->start = node->start; new->end = new->start + n_length; node->start = new->end; new->is_alloc = true; + new->next = node; return (void *) new->start; } }