diff --git a/.gitignore b/.gitignore index 11b797c..12095de 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ bin/ myos.bin boot.iso +.vscode/ diff --git a/include/gdt.h b/include/gdt.h new file mode 100644 index 0000000..3a7a4f3 --- /dev/null +++ b/include/gdt.h @@ -0,0 +1,100 @@ +#ifndef GDT_H +#define GDT_H + +#include + +extern char _end[], _edata[]; + +#define KERNEL_CS 0x08 /* kernel code segment */ +#define KERNEL_DS 0x10 /* kernel data segment */ +#define USER_CS 0x18 /* user code segment */ +#define USER_DS 0x20 /* user data segment */ +#define TSS 0x28 /* TSS segment */ + +#define KERNEL_BSS_SIZE ((int)_end - (int)_edata) + +#define NR_GDT_ENTRIES 6 /* entries in GDT descriptor */ +#define NR_IDT_ENTRIES 256 /* entries in IDT descriptor */ + +/* low flags of Segment Descriptors */ +#define SD_CODE 0x0A /* CODE Exec/Read */ +#define SD_DATA 0x02 /* DATA Read/Write */ + +#define SD_32INTRGATE 0x0E /* 32-bit Interrupt Gate (0D110) */ +#define SD_32TRAPGATE 0x0F /* 32-bit Trap Gate (0D111) */ + +#define SD_CD 0x10 /* 0 = system / 1 = code/data */ +#define SD_DPL0 0x00 /* priority level 0 (kernel) */ +#define SD_DPL3 0x60 /* priority level 3 (user) */ +#define SD_PRESENT 0x80 /* segment present or valid */ + +/* high flags Segment Descriptors */ +#define SD_OPSIZE32 0x04 /* 32-bit code and data segments */ +#define SD_PAGE4KB 0x08 /* page granularity (4KB) */ + +/* low flags of the TSS Descriptors */ +#define SD_TSSPRESENT 0x89 /* TSS present and not busy flag */ + +/* EFLAGS */ +#define EF_IOPL 12 /* IOPL bit */ + +struct desc_r { + uint16_t limit; + uint32_t base_addr; +} __attribute__((packed)); + +struct seg_desc { + unsigned sd_lolimit : 16; /* segment limit 0-15 bits */ + unsigned sd_lobase : 24; /* base address 0-23 bits */ + unsigned sd_loflags : 8; /* flags (P, DPL, S and TYPE) */ + unsigned sd_hilimit : 4; /* segment limit 16-19 bits */ + unsigned sd_hiflags : 4; /* flags (G, DB, 0 and AVL) */ + unsigned sd_hibase : 8; /* base address 24-31 bits */ +} __attribute__((packed)); + +struct gate_desc { + unsigned gd_looffset: 16; /* offset 0-15 bits */ + unsigned gd_selector: 16; /* segment selector */ + unsigned gd_flags : 16; /* flags (P, DPL, TYPE, 0 and NULL) */ + unsigned gd_hioffset: 16; /* offset 16-31 bits */ +} __attribute__((packed)); + +struct tss_entry_struct { + uint32_t prev_tss; // The previous TSS - with hardware task switching these form a kind of backward linked list. + uint32_t esp0; // The stack pointer to load when changing to kernel mode. + uint32_t ss0; // The stack segment to load when changing to kernel mode. + // Everything below here is unused. + uint32_t esp1; // esp and ss 1 and 2 would be used when switching to rings 1 or 2. + uint32_t ss1; + uint32_t esp2; + uint32_t ss2; + uint32_t cr3; + uint32_t eip; + uint32_t eflags; + uint32_t eax; + uint32_t ecx; + uint32_t edx; + uint32_t ebx; + uint32_t esp; + uint32_t ebp; + uint32_t esi; + uint32_t edi; + uint32_t es; + uint32_t cs; + uint32_t ss; + uint32_t ds; + uint32_t fs; + uint32_t gs; + uint32_t ldt; + uint16_t trap; + uint16_t iomap_base; +} __packed; + +struct seg_desc gdt[NR_GDT_ENTRIES]; + +struct desc_r gdtr = { + sizeof(gdt) - 1, + (uint32_t)&gdt +}; + +#endif diff --git a/include/paging.h b/include/paging.h index 8f2a0f5..dfecd1e 100644 --- a/include/paging.h +++ b/include/paging.h @@ -4,12 +4,27 @@ #include "../include/stdio.h" #include +#define PAGE_OFFSET 0xC0000000 +#define PAGE_SIZE 4096 +#define PAGE_SHIFT 0x0C + +#define PAGE_MASK ~(PAGE_SIZE - 1) /* 0xFFFFF000 */ +#define PAGE_ALIGN(addr) (((addr) + (PAGE_SIZE - 1)) & PAGE_MASK) + +#define PAGE_PRESENT 0x1 +#define PAGE_RW 0x002 /* Read/Write */ +#define PAGE_USER 0x004 /* User */ +#define PAGE_NOALLOC 0x200 /* No Page Allocated (OS managed) */ + +#define GDT_BASE (0xFFFFFFFF - (PAGE_OFFSET - 1)) + +#define GET_PGDIR(address) ((uint32_t)((address) >> 22) & 0x3FF) +#define GET_PGTBL(address) ((uint32_t)((address) >> 12) & 0x3FF) extern uint32_t kernel_page_directory[1024] __attribute__((aligned(4096))); extern uint32_t kernel_page_table[1024] __attribute__((aligned(4096))); extern uint32_t user_page_table[1024] __attribute__((aligned(4096))); - //paging.c void enablePaging(); void loadPageDirectory(uint32_t* page_directory); diff --git a/src/gdt.asm b/src/gdt.asm deleted file mode 100644 index a9c61a6..0000000 --- a/src/gdt.asm +++ /dev/null @@ -1,61 +0,0 @@ -section .gdt - -extern tss ; Объявляем tss как внешний символ из .data -extern tss_end - -gdt_start: - ; null entry - dd 0 - dd 0 - -gdt_code: - dw 0xffff ; 00-15 limit - dw 0 ; 16-31 base - db 0 ; 32-39 base - db 10011010b ; 40-47 access - db 11101111b ; 48-55 limit (48-51) and flags (52-55) - db 0 ; 56-63 base - -gdt_data: - dw 0xffff ; 00-15 limit - dw 0 ; 16-31 base - db 0 ; 32-39 base - db 10010010b ; 40-47 access - db 11101111b ; 48-55 limit (48-51) and flags (52-55) - db 0 ; 56-63 base - -gdt_code_ring3: - dw 0xffff - dw 0 - db 0 - db 11111010b - db 11101111b - db 0 - -gdt_data_ring3: - dw 0xffff - dw 0 - db 0 - db 11110010b - db 11101111b - db 0 - -gdt_tss: - dw 103 ;tss_end - tss - 1 ; Limit (размер TSS - 1) - dw 0 ; Base (будет заполнено вручную в boot.asm) - db 0 ; Base (средние 8 бит) - db 10001001b ; Access: Present, Ring 0, Type 9 (Available TSS) - db 00000000b ; Limit (48-51) и Flags (52-55): Granularity=0, Size=0 - db 0 ; Base (верхние 8 бит) - -gdt_end: - -gdt: - dw gdt_end - gdt_start - 1 - dd gdt_start - -CODE_SEG equ gdt_code - gdt_start -DATA_SEG equ gdt_data - gdt_start -CODE_SEG_RING3 equ gdt_code_ring3 - gdt_start -DATA_SEG_RING3 equ gdt_data_ring3 - gdt_start -TSS_SEG equ gdt_tss - gdt_start diff --git a/src/kernel/gdt.c b/src/kernel/gdt.c index b49522d..5cfe527 100644 --- a/src/kernel/gdt.c +++ b/src/kernel/gdt.c @@ -1,36 +1,16 @@ -//#include "../include/gdt.h" -#include +#include "../include/gdt.h" #include "../include/string.h" +#include "../include/paging.h" -struct desc_r { - uint16_t limit; - uint32_t base_addr; -} __attribute__((packed)); - -struct seg_desc { - unsigned sd_lolimit : 16; /* segment limit 0-15 bits */ - unsigned sd_lobase : 24; /* base address 0-23 bits */ - unsigned sd_loflags : 8; /* flags (P, DPL, S and TYPE) */ - unsigned sd_hilimit : 4; /* segment limit 16-19 bits */ - unsigned sd_hiflags : 4; /* flags (G, DB, 0 and AVL) */ - unsigned sd_hibase : 8; /* base address 24-31 bits */ -} __attribute__((packed)); - -struct gate_desc { - unsigned gd_looffset: 16; /* offset 0-15 bits */ - unsigned gd_selector: 16; /* segment selector */ - unsigned gd_flags : 16; /* flags (P, DPL, TYPE, 0 and NULL) */ - unsigned gd_hioffset: 16; /* offset 16-31 bits */ -} __attribute__((packed)); - -extern char _end[], _edata[]; - -#define KERNEL_CS 0x08 /* kernel code segment */ -#define KERNEL_DS 0x10 /* kernel data segment */ -#define USER_CS 0x18 /* user code segment */ -#define USER_DS 0x20 /* user data segment */ -#define TSS 0x28 /* TSS segment */ +void bss_init() +{ + memset((void *)((int)_edata), 0, KERNEL_BSS_SIZE); +} +uint32_t get_last_boot_addr() +{ + return ((uint32_t)_end & PAGE_MASK) + PAGE_SIZE; +} void load_gdt(uint32_t gdt_ptr) { asm volatile ( @@ -49,95 +29,7 @@ void load_gdt(uint32_t gdt_ptr) { ); } -#define PAGE_SIZE 4096 -#define PAGE_SHIFT 0x0C - -#define PAGE_MASK ~(PAGE_SIZE - 1) /* 0xFFFFF000 */ -#define PAGE_ALIGN(addr) (((addr) + (PAGE_SIZE - 1)) & PAGE_MASK) - -#define KERNEL_BSS_SIZE ((int)_end - (int)_edata) - -#define NR_GDT_ENTRIES 6 /* entries in GDT descriptor */ -#define NR_IDT_ENTRIES 256 /* entries in IDT descriptor */ - -/* low flags of Segment Descriptors */ -#define SD_CODE 0x0A /* CODE Exec/Read */ -#define SD_DATA 0x02 /* DATA Read/Write */ - -#define SD_32INTRGATE 0x0E /* 32-bit Interrupt Gate (0D110) */ -#define SD_32TRAPGATE 0x0F /* 32-bit Trap Gate (0D111) */ - -#define SD_CD 0x10 /* 0 = system / 1 = code/data */ -#define SD_DPL0 0x00 /* priority level 0 (kernel) */ -#define SD_DPL3 0x60 /* priority level 3 (user) */ -#define SD_PRESENT 0x80 /* segment present or valid */ - -/* high flags Segment Descriptors */ -#define SD_OPSIZE32 0x04 /* 32-bit code and data segments */ -#define SD_PAGE4KB 0x08 /* page granularity (4KB) */ - -/* low flags of the TSS Descriptors */ -#define SD_TSSPRESENT 0x89 /* TSS present and not busy flag */ - -/* EFLAGS */ -#define EF_IOPL 12 /* IOPL bit */ - -#define KERNEL_CS 0x08 /* kernel code segment */ -#define KERNEL_DS 0x10 /* kernel data segment */ -#define USER_CS 0x18 /* user code segment */ -#define USER_DS 0x20 /* user data segment */ -#define TSS 0x28 /* TSS segment */ - - -struct tss_entry_struct { - uint32_t prev_tss; // The previous TSS - with hardware task switching these form a kind of backward linked list. - uint32_t esp0; // The stack pointer to load when changing to kernel mode. - uint32_t ss0; // The stack segment to load when changing to kernel mode. - // Everything below here is unused. - uint32_t esp1; // esp and ss 1 and 2 would be used when switching to rings 1 or 2. - uint32_t ss1; - uint32_t esp2; - uint32_t ss2; - uint32_t cr3; - uint32_t eip; - uint32_t eflags; - uint32_t eax; - uint32_t ecx; - uint32_t edx; - uint32_t ebx; - uint32_t esp; - uint32_t ebp; - uint32_t esi; - uint32_t edi; - uint32_t es; - uint32_t cs; - uint32_t ss; - uint32_t ds; - uint32_t fs; - uint32_t gs; - uint32_t ldt; - uint16_t trap; - uint16_t iomap_base; -} __packed; - -void bss_init() -{ - memset((void *)((int)_edata), 0, KERNEL_BSS_SIZE); -} - -uint32_t get_last_boot_addr() -{ - return ((unsigned int)_end & PAGE_MASK) + PAGE_SIZE; -} - -struct seg_desc gdt[NR_GDT_ENTRIES]; - -struct desc_r gdtr = { - sizeof(gdt) - 1, - (unsigned int)&gdt -}; - -static void gdt_set_entry(int num, unsigned int base_addr, unsigned int limit, char loflags, char hiflags) +static void gdt_set_entry(int num, uint32_t base_addr, uint32_t limit, char loflags, char hiflags) { num /= sizeof(struct seg_desc); gdt[num].sd_lolimit = limit & 0xFFFF; @@ -150,7 +42,7 @@ static void gdt_set_entry(int num, unsigned int base_addr, unsigned int limit, c void gdt_init(void) { - unsigned char loflags; + uint8_t loflags; gdt_set_entry(0, 0, 0, 0, 0); /* null descriptor */ @@ -167,5 +59,5 @@ void gdt_init(void) loflags = SD_TSSPRESENT; gdt_set_entry(TSS, 0, sizeof(struct tss_entry_struct), loflags, SD_OPSIZE32); - load_gdt((unsigned int)&gdtr); + load_gdt((uint32_t)&gdtr); } diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index b5ecc58..1851895 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -155,9 +155,9 @@ void kmain(unsigned int magic, unsigned int info) apply_pic_masks(); - paging_init(); - printf("paging_init done\n"); - test_paging(); + //paging_init(); + //printf("paging_init done\n"); + //test_paging(); init_allocator(); heap_init(); printf("after heap_init\n"); diff --git a/src/mm/paging.c b/src/mm/paging.c index 0fad5af..913c563 100644 --- a/src/mm/paging.c +++ b/src/mm/paging.c @@ -7,31 +7,13 @@ uint32_t kernel_page_directory[1024] __attribute__((aligned(4096))); uint32_t kernel_page_table[1024] __attribute__((aligned(4096))); uint32_t user_page_table[1024] __attribute__((aligned(4096))); -#define PAGE_OFFSET 0xC0000000 -#define PAGE_SIZE 4096 +uint32_t *kpage_dir; -#define PAGE_PRESENT 0x1 -#define PAGE_RW 0x002 /* Read/Write */ -#define PAGE_USER 0x004 /* User */ -#define PAGE_NOALLOC 0x200 /* No Page Allocated (OS managed) */ - -#define PAGE_SHIFT 0x0C -#define PAGE_MASK ~(PAGE_SIZE - 1) /* 0xFFFFF000 */ - -#define GDT_BASE (0xFFFFFFFF - (PAGE_OFFSET - 1)) - -#define GET_PGDIR(address) ((unsigned int)((address) >> 22) & 0x3FF) -#define GET_PGTBL(address) ((unsigned int)((address) >> 12) & 0x3FF) - -#define PAGE_ALIGN(addr) (((addr) + (PAGE_SIZE - 1)) & PAGE_MASK) - -unsigned int *kpage_dir; - -unsigned int setup_tmp_pgdir(unsigned int magic, unsigned int info) +uint32_t setup_tmp_pgdir(uint32_t magic, uint32_t info) { int n, pd; - unsigned int addr, memksize; - unsigned int *pgtbl; + uint32_t pagedir_address, memksize; + uint32_t *page_table; struct multiboot_info *mbi; if(magic != MULTIBOOT_BOOTLOADER_MAGIC) { @@ -44,33 +26,41 @@ unsigned int setup_tmp_pgdir(unsigned int magic, unsigned int info) memksize = 4096; } else { /* we need to add the first 1MB to memksize */ - memksize = (unsigned int)mbi->mem_upper + 1024; - /* CONFIG_VM_SPLIT22 marks the maximum physical memory supported */ + memksize = (uint32_t)mbi->mem_upper + 1024; if(memksize > ((0xFFFFFFFF - PAGE_OFFSET) / 1024)) { memksize = (0xFFFFFFFF - PAGE_OFFSET) / 1024; } } } - addr = PAGE_OFFSET + (memksize * 1024) - memksize; - addr = PAGE_ALIGN(addr); + /* address becomes PAGE_OFFSET (0xC0000000) plus the size of memory minus the first page */ + /* TODO: check if I wrote the comment above correctly*/ + pagedir_address = PAGE_OFFSET + (memksize * 1024) - memksize; + pagedir_address = PAGE_ALIGN(pagedir_address); - kpage_dir = (unsigned int *)addr; + /* + memory pages: + 0 -> page directory + 1 -> page table + */ + kpage_dir = (uint32_t *)pagedir_address; memset(kpage_dir, 0, PAGE_SIZE); - addr += PAGE_SIZE; - pgtbl = (unsigned int *)addr; - memset(pgtbl, 0, memksize); + pagedir_address += PAGE_SIZE; + page_table = (uint32_t *)pagedir_address; + memset(page_table, 0, memksize); - for(n = 0; n < memksize / sizeof(unsigned int); n++) { - pgtbl[n] = (n << PAGE_SHIFT) | PAGE_PRESENT | PAGE_RW; + /* if we have 4MB assumed earlier, the memksize will be 4096 and this loop will run while n < 1024 */ + /* so basically 4MB is 1024 pages */ + for(n = 0; n < memksize / sizeof(uint32_t); n++) { + page_table[n] = (n << PAGE_SHIFT) | PAGE_PRESENT | PAGE_RW; if(!(n % 1024)) { pd = n / 1024; - kpage_dir[pd] = (unsigned int)(addr + (PAGE_SIZE * pd) + GDT_BASE) | PAGE_PRESENT | PAGE_RW; - kpage_dir[GET_PGDIR(PAGE_OFFSET) + pd] = (unsigned int)(addr + (PAGE_SIZE * pd) + GDT_BASE) | PAGE_PRESENT | PAGE_RW; + kpage_dir[pd] = (uint32_t)(pagedir_address + (PAGE_SIZE * pd) + GDT_BASE) | PAGE_PRESENT | PAGE_RW; + kpage_dir[GET_PGDIR(PAGE_OFFSET) + pd] = (uint32_t)(pagedir_address + (PAGE_SIZE * pd) + GDT_BASE) | PAGE_PRESENT | PAGE_RW; } } - return (unsigned int)kpage_dir - PAGE_OFFSET; + return (uint32_t)kpage_dir - PAGE_OFFSET; } void enablePaging() {