From 5cb95d816f3f916676f9808d3e938612215c450b Mon Sep 17 00:00:00 2001 From: pjht Date: Tue, 30 Apr 2019 17:11:26 -0500 Subject: [PATCH] long mode paging work --- Makefile | 2 +- bochsrc.txt | 2 +- cpu/x86_64/boot.asm | 11 ++- cpu/x86_64/cpu_init.c | 14 ++-- cpu/x86_64/long_start.asm | 1 + cpu/x86_64/paging.c | 103 +++++++++++++++++++++++ cpu/x86_64/paging.h | 10 +++ cpu/x86_64/pmem.c | 123 +++++++++++++++++++++++++++ cpu/x86_64/pmem.h | 10 +++ kernel/kernel.c | 170 +++++++++++++++++++------------------- 10 files changed, 349 insertions(+), 97 deletions(-) create mode 100644 cpu/x86_64/paging.c create mode 100644 cpu/x86_64/paging.h create mode 100644 cpu/x86_64/pmem.c create mode 100644 cpu/x86_64/pmem.h diff --git a/Makefile b/Makefile index 6cd7514..4b9fd45 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -PLAT=x86_64 +PLAT=i386 C_SOURCES = $(wildcard kernel/*.c drivers/$(PLAT)/*.c drivers/$(PLAT)/*/*.c cpu/$(PLAT)/*.c fs/*.c) ASM = $(wildcard cpu/$(PLAT)/*.asm) S_ASM = $(wildcard cpu/$(PLAT)/*.s) diff --git a/bochsrc.txt b/bochsrc.txt index d422376..2c06d9e 100644 --- a/bochsrc.txt +++ b/bochsrc.txt @@ -10,7 +10,7 @@ floppy_bootsig_check: disabled=0 # no floppya # no floppyb ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 -ata0-master: type=disk, path=ext2.img, mode=flat, cylinders=65, heads=16, spt=63, model="Generic 1234", biosdetect=auto, translation=auto +ata0-master: type=none, path=ext2.img, mode=flat, cylinders=65, heads=16, spt=63, model="Generic 1234", biosdetect=auto, translation=auto ata0-slave: type=cdrom, path=os.iso, status=inserted, model="Generic 1234", biosdetect=auto ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15 ata1-master: type=none diff --git a/cpu/x86_64/boot.asm b/cpu/x86_64/boot.asm index e22c4ee..4afca1e 100644 --- a/cpu/x86_64/boot.asm +++ b/cpu/x86_64/boot.asm @@ -6,8 +6,14 @@ header_start: ; checksum dd 0x100000000 - (0xe85250d6 + 0 + (header_end - header_start)) - ; insert optional multiboot tags here - + ; info request tag + info_tag_start: + dw 1 ; type + dw 0 ; flags + dd info_tag_end-info_tag_start ;size + dd 6 ; full memory map (available and reserved ranges) + info_tag_end: + dd 0 ; tag alignment ; required end tag dw 0 ; type dw 0 ; flags @@ -21,6 +27,7 @@ section .boot.text bits 32 start: mov esp, stack_top + mov edi, ebx call check_multiboot call check_cpuid diff --git a/cpu/x86_64/cpu_init.c b/cpu/x86_64/cpu_init.c index 72d81fc..7225c2b 100644 --- a/cpu/x86_64/cpu_init.c +++ b/cpu/x86_64/cpu_init.c @@ -1,15 +1,13 @@ -// #include "gdt.h" -// #include "paging.h" +#include "paging.h" #include "isr.h" -#include -// #include "pmem.h" +#include +#include "pmem.h" // #include "../tasking.h" -void cpu_init(multiboot_info_t* mbd) { - // gdt_init(); +void cpu_init(struct multiboot_boot_header_tag* mbd) { isr_install(); asm volatile("sti"); - // pmem_init(mbd); - // paging_init(); + pmem_init(mbd); + paging_init(); // tasking_init(); } diff --git a/cpu/x86_64/long_start.asm b/cpu/x86_64/long_start.asm index 43277da..ccc8685 100644 --- a/cpu/x86_64/long_start.asm +++ b/cpu/x86_64/long_start.asm @@ -4,6 +4,7 @@ extern kmain section .boot.text bits 64 long_mode_start: + xchg bx,bx mov ax, 0 mov ss, ax mov ds, ax diff --git a/cpu/x86_64/paging.c b/cpu/x86_64/paging.c new file mode 100644 index 0000000..fe9ac2a --- /dev/null +++ b/cpu/x86_64/paging.c @@ -0,0 +1,103 @@ +#include +#include "paging.h" +#include "pmem.h" + +static uint64_t pml4[512] __attribute__((aligned(4096))); +static uint64_t pdpt[512] __attribute__((aligned(4096))); +static uint64_t page_directory[512] __attribute__((aligned(4096))); +uint64_t* curr_structs=(uint64_t*)0xFFFFFF8000000000; + + +uint64_t get_pml4_entry(int entry) { + return ((uint64_t*)(((char*)curr_structs)+0x7FFFFFF000))[entry]; +} + +uint64_t get_pdpt_entry(int pml4_entry,int entry) { + return ((uint64_t*)(((char*)curr_structs)+0x7FFFE00000))[(pml4_entry<<9)+entry]; +} + + +uint64_t get_page_dir_entry(int pml4_entry,int pdpt_entry, int entry) { + return ((uint64_t*)(((char*)curr_structs)+0x7FC0000000))[(pml4_entry<<18)+(pdpt_entry<<9)+entry]; +} + +uint64_t get_page_table_entry(int pml4_entry,int pdpt_entry, int pdir_entry, int entry) { + return ((uint64_t*)(((char*)curr_structs)+0x7000000000))[(pml4_entry<<27)+(pdpt_entry<<18)+(pdir_entry<<9)+entry]; +} + +void set_pml4_entry(int entry,uint64_t mapping) { + ((uint64_t*)(((char*)curr_structs)+0x7FFFFFF000))[entry]=mapping; +} + +void set_pdpt_entry(int pml4_entry,int entry,uint64_t mapping) { + ((uint64_t*)(((char*)curr_structs)+0x7FFFE00000))[(pml4_entry<<9)+entry]=mapping; +} + +void set_page_dir_entry(int pml4_entry,int pdpt_entry, int entry,uint64_t mapping) { + ((uint64_t*)(((char*)curr_structs)+0x7FC0000000))[(pml4_entry<<18)+(pdpt_entry<<9)+entry]=mapping; +} + +void set_page_table_entry(int pml4_entry,int pdpt_entry, int pdir_entry, int entry,uint64_t mapping) { + ((uint64_t*)(((char*)curr_structs)+0x7000000000))[(pml4_entry<<27)+(pdpt_entry<<18)+(pdir_entry<<9)+entry]=mapping; +} + +uint32_t find_free_page() { + for (int a=0;a<512;a++) { + if (get_pml4_entry(a)&0x1) { + for (int b=0;b<512;b++) { + if (get_pdpt_entry(a,b)&0x1) { + for (int c=0;c<512;c++) { + if (get_page_dir_entry(a,b,c)&0x1) { + for (int d=0;d<512;d++) { + if (!(get_page_table_entry(a,b,c,d)&0x1)) { + return (a<<27)+(b<<18)+(c<<9)+d; + } + } // end for d + } else { + uint64_t addr=pmem_alloc(1); + set_page_dir_entry(a,b,c,addr|0x7); + return (a<<27)+(b<<18)+(c<<9); + } // end if abc + } // end for c + } else { + uint64_t addr=pmem_alloc(1); + set_pdpt_entry(a,b,addr|0x7); + addr=pmem_alloc(1); + set_page_dir_entry(a,b,0,addr|0x7); + return (a<<27)+(b<<18); + } // end if ab + } // end for b + } else { + uint64_t addr=pmem_alloc(1); + set_pml4_entry(a,addr|0x7); + addr=pmem_alloc(1); + set_pdpt_entry(a,0,addr|0x7); + addr=pmem_alloc(1); + set_page_dir_entry(a,0,0,addr|0x7); + return a<<27; + } //end if a + } // end for a + return 0; +} + +void paging_init() { + pml4[0]=(((uint64_t)&pdpt)-0xffff800000000000)|0x7; + pml4[256]=(((uint64_t)&pdpt)-0xffff800000000000)|0x7; + pml4[511]=(((uint64_t)&pml4)-0xffff800000000000)|0x7; + pdpt[0]=(((uint64_t)&page_directory)-0xffff800000000000)|0x7; + for (int i=0;i + +#define NUM_KERN_DIRS 4 + +void paging_init(); + +#endif diff --git a/cpu/x86_64/pmem.c b/cpu/x86_64/pmem.c new file mode 100644 index 0000000..fcaa123 --- /dev/null +++ b/cpu/x86_64/pmem.c @@ -0,0 +1,123 @@ +#include +#include "../halt.h" +#include +#include +#include + +static char bmap[131072]; + +static char get_bmap_bit(int index) { + int byte=index/8; + int bit=index%8; + char entry=bmap[byte]; + return (entry&(1<0; +} + +static void set_bmap_bit(int index) { + int byte=index/8; + int bit=index%8; + bmap[byte]=bmap[byte]|(1<type!=0) { + switch (tag->type) { + case MULTIBOOT_TAG_TYPE_MMAP: { + found_mmap=1; + struct multiboot_mmap_entry* orig_ptr=(struct multiboot_mmap_entry*)(((char*)tag)+16); + for (struct multiboot_mmap_entry* ptr=orig_ptr;(char*)ptr<((char*)orig_ptr)+tag->size;ptr++) { + if (ptr->type!=MULTIBOOT_MEMORY_AVAILABLE) continue; + uint32_t size=ptr->len; + uint32_t start=ptr->addr; + if (start<0x100000) continue; + uint32_t end=start+ptr->len-1; + if (start&0xFFF) { + start+=0x1000; + } + start=start>>12; + end=end>>12; + for (uint32_t i=start;isize+7)&0xFFFFFFF8)); + } + if (!found_mmap) { + vga_write_string("[PANIC] No memory map supplied by bootloader!"); + halt(); + } + for (uint32_t i=0;i<2048;i++) { + set_bmap_bit(i); + } +} + +void* pmem_alloc(int num_pages) { + uint32_t bmap_index; + uint32_t remaining_blks; + for(uint32_t i=0;i<131072;i++) { + if (bmap[i]!=0xFF) { + char got_0=0; + remaining_blks=num_pages; + uint32_t old_j; + for (uint32_t j=i*8;;j++) { + char bit=get_bmap_bit(j); + if (got_0) { + if (bit) { + if (remaining_blks==0) { + bmap_index=old_j; + break; + } else { + i+=j/8; + i--; + break; + } + } else { + remaining_blks--; + } + } else { + if (!bit) { + got_0=1; + old_j=j; + remaining_blks--; + } + } + if (remaining_blks==0) { + bmap_index=old_j; + break; + } + } + } + if (remaining_blks==0) { + break; + } + } + if (remaining_blks!=0) { + return NULL; + } + for (int i=0;i + +void pmem_init(struct multiboot_boot_header_tag* tags); +void* pmem_alloc(int num_pages); +void pmem_free(int start_page,int num_pages); + +#endif diff --git a/kernel/kernel.c b/kernel/kernel.c index ae075bc..a33c0ed 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -24,33 +24,33 @@ static long initrd_sz; static char* initrd; typedef int (*func_ptr)(); -// static int console_dev_drv(char* filename,int c,long pos,char wr) { -// if (wr) { -// if (c=='\f') { -// vga_clear(); -// } else if (c=='\b') { -// vga_backspace(); -// } -// char str[2]; -// str[0]=(char)c; -// str[1]='\0'; -// vga_write_string(str); -// return 0; -// } else { -// return 0; -// // return devbuf_get(kbd_buf); -// } -// } +static int console_dev_drv(char* filename,int c,long pos,char wr) { + if (wr) { + if (c=='\f') { + vga_clear(); + } else if (c=='\b') { + vga_backspace(); + } + char str[2]; + str[0]=(char)c; + str[1]='\0'; + vga_write_string(str); + return 0; + } else { + return 0; + // return devbuf_get(kbd_buf); + } +} -// static int initrd_dev_drv(char* filename,int c,long pos,char wr) { -// if (wr) { -// return 0; -// } -// if (pos>=initrd_sz) { -// return EOF; -// } -// return initrd[pos]; -// } +static int initrd_dev_drv(char* filename,int c,long pos,char wr) { + if (wr) { + return 0; + } + if (pos>=initrd_sz) { + return EOF; + } + return initrd[pos]; +} // static void read_initrd(multiboot_info_t* mbd) { // if ((mbd->flags&MULTIBOOT_INFO_MODS)!=0) { @@ -76,58 +76,58 @@ typedef int (*func_ptr)(); // } // } -// static void init() { -// init_vfs(); -// init_devfs(); -// devfs_add(console_dev_drv,"console"); -// stdout=fopen("/dev/console","w"); -// stdin=fopen("/dev/console","r"); -// stderr=fopen("/dev/console","w"); -// // read_initrd(mbd); -// // devfs_add(initrd_dev_drv,"initrd"); -// // initrd_init(); -// // mount("/initrd/","","initrd"); -// // Detect PCI -// port_long_out(0xCF8,(1<<31)); -// uint32_t word=port_long_in(0xCFC); -// port_long_out(0xCF8,(1<<31)|0x4); -// if (word!=port_long_in(0xCFC)) { -// // pci_init(); -// } -// // Detect and initailize serial ports -// serial_init(); -// // FILE* file=fopen("/initrd/prog.elf","r"); -// // elf_header header; -// // fread(&header,sizeof(elf_header),1,file); -// // if (header.magic!=ELF_MAGIC) { -// // klog("INFO","Invalid magic number for prog.elf"); -// // fclose(file); -// // } else { -// // fseek(file,header.prog_hdr,SEEK_SET); -// // elf_pheader pheader; -// // fread(&pheader,sizeof(elf_pheader),1,file); -// // alloc_memory_virt(1,(void*)pheader.vaddr); -// // fseek(file,pheader.offset,SEEK_SET); -// // fread((void*)pheader.vaddr,pheader.filesz,1,file); -// // klog("INFO","VADDR:%x",pheader.vaddr); -// // func_ptr prog=(func_ptr)header.entry; -// // int val=prog(); -// // klog("INFO","RAN PROG:%d",val); -// // } -// ide_init(); -// load_parts("/dev/hda"); -// init_ext2(); -// mount("/","/dev/hda1","ext2"); -// klog("INFO","MOUNT"); -// FILE* f=fopen("/file","r"); -// char str[256]; -// fgets(str,256,f); -// str[strlen(str)-1]='\0'; -// klog("INFO","Got string %s",str); -// for(;;) { -// yield(); -// } -// } +static void init() { + init_vfs(); + init_devfs(); + devfs_add(console_dev_drv,"console"); + stdout=fopen("/dev/console","w"); + stdin=fopen("/dev/console","r"); + stderr=fopen("/dev/console","w"); + // read_initrd(mbd); + // devfs_add(initrd_dev_drv,"initrd"); + // initrd_init(); + // mount("/initrd/","","initrd"); + // Detect PCI + port_long_out(0xCF8,(1<<31)); + uint32_t word=port_long_in(0xCFC); + port_long_out(0xCF8,(1<<31)|0x4); + if (word!=port_long_in(0xCFC)) { + // pci_init(); + } + // Detect and initailize serial ports + serial_init(); + // FILE* file=fopen("/initrd/prog.elf","r"); + // elf_header header; + // fread(&header,sizeof(elf_header),1,file); + // if (header.magic!=ELF_MAGIC) { + // klog("INFO","Invalid magic number for prog.elf"); + // fclose(file); + // } else { + // fseek(file,header.prog_hdr,SEEK_SET); + // elf_pheader pheader; + // fread(&pheader,sizeof(elf_pheader),1,file); + // alloc_memory_virt(1,(void*)pheader.vaddr); + // fseek(file,pheader.offset,SEEK_SET); + // fread((void*)pheader.vaddr,pheader.filesz,1,file); + // klog("INFO","VADDR:%x",pheader.vaddr); + // func_ptr prog=(func_ptr)header.entry; + // int val=prog(); + // klog("INFO","RAN PROG:%d",val); + // } + ide_init(); + load_parts("/dev/hda"); + init_ext2(); + mount("/","/dev/hda1","ext2"); + klog("INFO","MOUNT"); + FILE* f=fopen("/file","r"); + char str[256]; + fgets(str,256,f); + str[strlen(str)-1]='\0'; + klog("INFO","Got string %s",str); + for(;;) { + yield(); + } +} void kmain(struct multiboot_boot_header_tag* tags) { cpu_init(tags); @@ -137,16 +137,16 @@ void kmain(struct multiboot_boot_header_tag* tags) { // info.width=header->framebuffer_width; // info.height=header->framebuffer_height; // } else { - info.address=(char*)0xffff8000000B8000; - // info.address=(char*)0xC00B8000; + // info.address=(char*)0xffff8000000B8000; + info.address=(char*)0xC00B8000; info.width=80; info.height=25; // } vga_init(info); vga_write_string("Hello long mode world!\n"); - // createTask(init); - // for (;;) { - // yield(); - // } - for(;;); + // check_gets(); + createTask(init); + for (;;) { + yield(); + } }