long mode paging work
This commit is contained in:
parent
5020cfa3dd
commit
5cb95d816f
2
Makefile
2
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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
103
cpu/x86_64/paging.c
Normal 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
10
cpu/x86_64/paging.h
Normal 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
123
cpu/x86_64/pmem.c
Normal 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
10
cpu/x86_64/pmem.h
Normal 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
|
170
kernel/kernel.c
170
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();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user