long mode paging work

This commit is contained in:
pjht 2019-04-30 17:11:26 -05:00
parent 5020cfa3dd
commit 5cb95d816f
10 changed files with 349 additions and 97 deletions

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -1,15 +1,13 @@
// #include "gdt.h"
// #include "paging.h"
#include "paging.h"
#include "isr.h"
#include <grub/multiboot.h>
// #include "pmem.h"
#include <grub/multiboot2.h>
#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();
}

View File

@ -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

103
cpu/x86_64/paging.c Normal file
View File

@ -0,0 +1,103 @@
#include <stdint.h>
#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<NUM_KERN_DIRS;i++) {
page_directory[i]=(i*0x200000)|0x87;
}
asm volatile("mov %0,%%cr3"::"r"((uint64_t)pml4-0xffff800000000000));
}
void check_gets() {
char str[256];
hex_to_ascii(find_free_page(),str);
vga_write_string(str);
vga_write_string("\n");
str[0]='\0';
hex_to_ascii(find_free_page(),str);
vga_write_string(str);
vga_write_string("\n");
}

10
cpu/x86_64/paging.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef PAGING_H
#define PAGING_H
#include <stdint.h>
#define NUM_KERN_DIRS 4
void paging_init();
#endif

123
cpu/x86_64/pmem.c Normal file
View File

@ -0,0 +1,123 @@
#include <grub/multiboot2.h>
#include "../halt.h"
#include <stdint.h>
#include <stdlib.h>
#include <klog.h>
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<<bit))>0;
}
static void set_bmap_bit(int index) {
int byte=index/8;
int bit=index%8;
bmap[byte]=bmap[byte]|(1<<bit);
}
static void clear_bmap_bit(int index) {
int byte=index/8;
int bit=index%8;
bmap[byte]=bmap[byte]&(~(1<<bit));
}
void pmem_init(struct multiboot_boot_header_tag* tags) {
for (int i=0;i<131072;i++) {
bmap[i]=0xFF;
}
char found_mmap=0;
struct multiboot_tag* tag=(struct multiboot_tag*)(tags+1);
while (tag->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;i<end;i++) {
clear_bmap_bit(i);
}
}
char str[256];
break;
}
}
tag=(struct multiboot_tag*)((char*)tag+((tag->size+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<num_pages;i++) {
set_bmap_bit(bmap_index+i);
}
void* addr=(void*)(bmap_index<<12);
return addr;
}
void pmem_free(int start_page,int num_pages) {
for (int i=start_page;i<num_pages;i++) {
set_bmap_bit(i);
}
}

10
cpu/x86_64/pmem.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef PMEM_H
#define PMEM_H
#include <grub/multiboot2.h>
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

View File

@ -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();
}
}